Re-commit r225674: Convert other drivers to use WrapperNode.
The original commit had an issue with Mac OS dylib files. It didn't handle fat binary dylib files correctly. This patch includes a fix. A test for that case has already been committed in r225764. llvm-svn: 226123
This commit is contained in:
parent
6725a83e84
commit
df230b21e3
|
@ -66,7 +66,7 @@ Readers are factories
|
|||
---------------------
|
||||
|
||||
The linker will usually only instantiate your Reader once. That one Reader will
|
||||
have its parseFile() method called many times with different input files.
|
||||
have its loadFile() method called many times with different input files.
|
||||
To support multithreaded linking, the Reader may be parsing multiple input
|
||||
files in parallel. Therefore, there should be no parsing state in you Reader
|
||||
object. Any parsing state should be in ivars of your File subclass or in
|
||||
|
@ -74,8 +74,8 @@ some temporary object.
|
|||
|
||||
The key method to implement in a reader is::
|
||||
|
||||
virtual error_code parseFile(LinkerInput &input,
|
||||
std::vector<std::unique_ptr<File>> &result);
|
||||
virtual error_code loadFile(LinkerInput &input,
|
||||
std::vector<std::unique_ptr<File>> &result);
|
||||
|
||||
It takes a memory buffer (which contains the contents of the object file
|
||||
being read) and returns an instantiated lld::File object which is
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
virtual const File *find(StringRef name, bool dataSymbolOnly) const = 0;
|
||||
|
||||
virtual std::error_code
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) const = 0;
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) = 0;
|
||||
|
||||
/// Returns a set of all defined symbols in the archive, i.e. all
|
||||
/// resolvable symbol using this file.
|
||||
|
|
|
@ -274,7 +274,8 @@ protected:
|
|||
/// can do unit testing a driver using non-existing file paths.
|
||||
class ErrorFile : public File {
|
||||
public:
|
||||
ErrorFile(StringRef p, std::error_code ec) : File(p, kindObject), _ec(ec) {}
|
||||
ErrorFile(StringRef path, std::error_code ec)
|
||||
: File(path, kindObject), _ec(ec) {}
|
||||
|
||||
std::error_code doParse() override { return _ec; }
|
||||
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
//===- lld/Driver/DarwinInputGraph.h - Input Graph Node for Mach-O linker -===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
///
|
||||
/// Handles Options for MachO linking and provides InputElements
|
||||
/// for MachO linker
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_DRIVER_DARWIN_INPUT_GRAPH_H
|
||||
#define LLD_DRIVER_DARWIN_INPUT_GRAPH_H
|
||||
|
||||
#include "lld/Core/ArchiveLibraryFile.h"
|
||||
#include "lld/Core/InputGraph.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
/// \brief Represents a MachO File
|
||||
class MachOFileNode : public FileNode {
|
||||
public:
|
||||
MachOFileNode(StringRef path, MachOLinkingContext &ctx)
|
||||
: FileNode(path), _context(ctx), _isWholeArchive(false),
|
||||
_upwardDylib(false) {}
|
||||
|
||||
/// \brief Parse the input file to lld::File.
|
||||
std::error_code parse(const LinkingContext &ctx,
|
||||
raw_ostream &diagnostics) override;
|
||||
|
||||
void setLoadWholeArchive(bool value=true) {
|
||||
_isWholeArchive = value;
|
||||
}
|
||||
|
||||
void setUpwardDylib(bool value=true) {
|
||||
_upwardDylib = value;
|
||||
}
|
||||
|
||||
private:
|
||||
void narrowFatBuffer(std::unique_ptr<MemoryBuffer> &mb, StringRef filePath);
|
||||
|
||||
MachOLinkingContext &_context;
|
||||
std::unique_ptr<const ArchiveLibraryFile> _archiveFile;
|
||||
bool _isWholeArchive;
|
||||
bool _upwardDylib;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
|
@ -36,7 +36,7 @@ typedef std::vector<std::unique_ptr<File>> FileVector;
|
|||
|
||||
FileVector makeErrorFile(StringRef path, std::error_code ec);
|
||||
FileVector parseMemberFiles(FileVector &files);
|
||||
FileVector parseFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
|
||||
FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
|
||||
|
||||
/// Base class for all Drivers.
|
||||
class Driver {
|
||||
|
@ -101,6 +101,11 @@ public:
|
|||
static bool parse(int argc, const char *argv[], MachOLinkingContext &info,
|
||||
raw_ostream &diagnostics = llvm::errs());
|
||||
|
||||
// Reads a file from disk to memory. Returns only a needed chunk
|
||||
// if a fat binary.
|
||||
static ErrorOr<std::unique_ptr<MemoryBuffer>>
|
||||
getMemoryBuffer(MachOLinkingContext &ctx, StringRef path);
|
||||
|
||||
private:
|
||||
DarwinLdDriver() LLVM_DELETED_FUNCTION;
|
||||
};
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
//===- lld/Driver/GnuLdInputGraph.h - Input Graph Node for ELF linker------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
///
|
||||
/// Handles Options for the GNU style linker for ELF and provides InputElements
|
||||
/// for the GNU style linker for ELF
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_DRIVER_GNU_LD_INPUT_GRAPH_H
|
||||
#define LLD_DRIVER_GNU_LD_INPUT_GRAPH_H
|
||||
|
||||
#include "lld/Core/ArchiveLibraryFile.h"
|
||||
#include "lld/Core/InputGraph.h"
|
||||
#include "lld/Core/Resolver.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
/// \brief Represents a ELF File
|
||||
class ELFFileNode : public FileNode {
|
||||
public:
|
||||
/// \brief The attributes class provides a way for a input file to look into
|
||||
/// all the positional attributes that were specified in the command line.
|
||||
/// There are few positional operators and the number of arguments to the
|
||||
/// ELFFileNode class keeps growing. This achieves code to be clean as well.
|
||||
class Attributes {
|
||||
public:
|
||||
Attributes()
|
||||
: _isWholeArchive(false), _asNeeded(false), _isDashlPrefix(false),
|
||||
_isSysRooted(false) {}
|
||||
void setWholeArchive(bool isWholeArchive) {
|
||||
_isWholeArchive = isWholeArchive;
|
||||
}
|
||||
void setAsNeeded(bool asNeeded) { _asNeeded = asNeeded; }
|
||||
void setDashlPrefix(bool isDashlPrefix) { _isDashlPrefix = isDashlPrefix; }
|
||||
void setSysRooted(bool isSysRooted) { _isSysRooted = isSysRooted; }
|
||||
|
||||
public:
|
||||
bool _isWholeArchive;
|
||||
bool _asNeeded;
|
||||
bool _isDashlPrefix;
|
||||
bool _isSysRooted;
|
||||
};
|
||||
|
||||
ELFFileNode(ELFLinkingContext &ctx, StringRef path, Attributes &attributes)
|
||||
: FileNode(path), _elfLinkingContext(ctx), _attributes(attributes) {}
|
||||
|
||||
ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;
|
||||
|
||||
/// \brief create an error string for printing purposes
|
||||
std::string errStr(std::error_code) override;
|
||||
|
||||
/// \brief Dump the Input Element
|
||||
bool dump(raw_ostream &diagnostics) override {
|
||||
diagnostics << "Name : " << *getPath(_elfLinkingContext) << "\n"
|
||||
<< "Type : ELF File\n"
|
||||
<< "Attributes :\n"
|
||||
<< " - wholeArchive : "
|
||||
<< ((_attributes._isWholeArchive) ? "true" : "false") << "\n"
|
||||
<< " - asNeeded : "
|
||||
<< ((_attributes._asNeeded) ? "true" : "false") << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Parse the input file to lld::File.
|
||||
std::error_code parse(const LinkingContext &, raw_ostream &) override;
|
||||
|
||||
private:
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
const ELFLinkingContext &_elfLinkingContext;
|
||||
std::unique_ptr<const ArchiveLibraryFile> _archiveFile;
|
||||
const Attributes _attributes;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
|
@ -1,45 +0,0 @@
|
|||
//===- lld/Driver/WinLinkInputGraph.h - Input Graph Node for COFF linker --===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
///
|
||||
/// Handles Options for PECOFF linking and provides InputElements
|
||||
/// for PECOFF linker
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_DRIVER_WIN_LINK_INPUT_GRAPH_H
|
||||
#define LLD_DRIVER_WIN_LINK_INPUT_GRAPH_H
|
||||
|
||||
#include "lld/Core/InputGraph.h"
|
||||
#include "lld/ReaderWriter/PECOFFLinkingContext.h"
|
||||
#include <map>
|
||||
|
||||
namespace lld {
|
||||
|
||||
/// \brief Represents a PECOFF File
|
||||
class PECOFFFileNode : public FileNode {
|
||||
public:
|
||||
PECOFFFileNode(PECOFFLinkingContext &ctx, StringRef path)
|
||||
: FileNode(path), _ctx(ctx), _parsed(false) {}
|
||||
|
||||
/// \brief Parse the input file to lld::File.
|
||||
std::error_code parse(const LinkingContext &ctx,
|
||||
raw_ostream &diagnostics) override;
|
||||
|
||||
protected:
|
||||
const PECOFFLinkingContext &_ctx;
|
||||
|
||||
private:
|
||||
bool _parsed;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
|
@ -290,6 +290,28 @@ public:
|
|||
bool alignSegments() const { return _alignSegments; }
|
||||
void setAlignSegments(bool align) { _alignSegments = align; }
|
||||
|
||||
/// \brief The attributes class provides a way for a input file to look into
|
||||
/// all the positional attributes that were specified in the command line.
|
||||
/// There are few positional operators and the number of arguments to the
|
||||
/// ELFFileNode class keeps growing. This achieves code to be clean as well.
|
||||
class Attributes {
|
||||
public:
|
||||
Attributes()
|
||||
: _isWholeArchive(false), _asNeeded(false), _isDashlPrefix(false),
|
||||
_isSysRooted(false) {}
|
||||
void setWholeArchive(bool isWholeArchive) {
|
||||
_isWholeArchive = isWholeArchive;
|
||||
}
|
||||
void setAsNeeded(bool asNeeded) { _asNeeded = asNeeded; }
|
||||
void setDashlPrefix(bool isDashlPrefix) { _isDashlPrefix = isDashlPrefix; }
|
||||
void setSysRooted(bool isSysRooted) { _isSysRooted = isSysRooted; }
|
||||
|
||||
bool _isWholeArchive;
|
||||
bool _asNeeded;
|
||||
bool _isDashlPrefix;
|
||||
bool _isSysRooted;
|
||||
};
|
||||
|
||||
private:
|
||||
ELFLinkingContext() LLVM_DELETED_FUNCTION;
|
||||
|
||||
|
|
|
@ -350,7 +350,7 @@ private:
|
|||
mutable llvm::StringMap<mach_o::MachODylibFile*> _pathToDylibMap;
|
||||
mutable std::set<mach_o::MachODylibFile*> _allDylibs;
|
||||
mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
|
||||
mutable std::vector<std::unique_ptr<class MachOFileNode>> _indirectDylibs;
|
||||
mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
|
||||
ExportMode _exportMode;
|
||||
llvm::StringSet<> _exportedSymbols;
|
||||
DebugInfoMode _debugInfoMode;
|
||||
|
|
|
@ -55,8 +55,8 @@ public:
|
|||
/// file) and create a File object.
|
||||
/// The resulting File object takes ownership of the MemoryBuffer.
|
||||
virtual std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const = 0;
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -93,8 +93,8 @@ public:
|
|||
|
||||
/// Walk the list of registered Readers and find one that can parse the
|
||||
/// supplied file and parse it.
|
||||
std::error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const;
|
||||
std::error_code loadFile(std::unique_ptr<MemoryBuffer> mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const;
|
||||
|
||||
/// Walk the list of registered kind tables to convert a Reference Kind
|
||||
/// name to a value.
|
||||
|
|
|
@ -12,14 +12,11 @@ add_public_tablegen_target(DriverOptionsTableGen)
|
|||
|
||||
add_lld_library(lldDriver
|
||||
CoreDriver.cpp
|
||||
DarwinInputGraph.cpp
|
||||
DarwinLdDriver.cpp
|
||||
Driver.cpp
|
||||
GnuLdDriver.cpp
|
||||
GnuLdInputGraph.cpp
|
||||
UniversalDriver.cpp
|
||||
WinLinkDriver.cpp
|
||||
WinLinkInputGraph.cpp
|
||||
WinLinkModuleDef.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
|
|||
|
||||
case OPT_INPUT: {
|
||||
std::vector<std::unique_ptr<File>> files
|
||||
= parseFile(ctx, inputArg->getValue(), false);
|
||||
= loadFile(ctx, inputArg->getValue(), false);
|
||||
for (std::unique_ptr<File> &file : files) {
|
||||
inputGraph->addInputElement(std::unique_ptr<InputElement>(
|
||||
new WrapperNode(std::move(file))));
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
//===- lib/ReaderWriter/MachO/DarwinInputGraph.cpp ------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/DarwinInputGraph.h"
|
||||
#include "lld/Core/ArchiveLibraryFile.h"
|
||||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "lld/Core/SharedLibraryFile.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
|
||||
/// \brief Parse the input file to lld::File.
|
||||
std::error_code MachOFileNode::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>> mbOrErr =
|
||||
MemoryBuffer::getFileOrSTDIN(*filePath);
|
||||
if (std::error_code ec = mbOrErr.getError())
|
||||
return ec;
|
||||
std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get());
|
||||
|
||||
_context.addInputFileDependency(*filePath);
|
||||
if (ctx.logInputFiles())
|
||||
diagnostics << *filePath << "\n";
|
||||
|
||||
narrowFatBuffer(mb, *filePath);
|
||||
|
||||
std::vector<std::unique_ptr<File>> parsedFiles;
|
||||
if (std::error_code ec = ctx.registry().parseFile(std::move(mb), parsedFiles))
|
||||
return ec;
|
||||
for (std::unique_ptr<File> &pf : parsedFiles) {
|
||||
// If file is a dylib, inform LinkingContext about it.
|
||||
if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(pf.get())) {
|
||||
_context.registerDylib(reinterpret_cast<mach_o::MachODylibFile*>(shl),
|
||||
_upwardDylib);
|
||||
}
|
||||
// If file is an archive and -all_load, then add all members.
|
||||
if (ArchiveLibraryFile *archive = dyn_cast<ArchiveLibraryFile>(pf.get())) {
|
||||
if (_isWholeArchive) {
|
||||
// Have this node own the FileArchive object.
|
||||
_archiveFile.reset(archive);
|
||||
pf.release();
|
||||
// Add all members to _files vector
|
||||
return archive->parseAllMembers(_files);
|
||||
}
|
||||
}
|
||||
_files.push_back(std::move(pf));
|
||||
}
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
|
||||
/// If buffer contains a fat file, find required arch in fat buffer and
|
||||
/// switch buffer to point to just that required slice.
|
||||
void MachOFileNode::narrowFatBuffer(std::unique_ptr<MemoryBuffer> &mb,
|
||||
StringRef filePath) {
|
||||
// Check if buffer is a "fat" file that contains needed arch.
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
if (!_context.sliceFromFatFile(*mb, offset, size)) {
|
||||
return;
|
||||
}
|
||||
// Create new buffer containing just the needed slice.
|
||||
auto subuf = MemoryBuffer::getFileSlice(filePath, size, offset);
|
||||
if (subuf.getError())
|
||||
return;
|
||||
// The assignment to mb will release previous buffer.
|
||||
mb = std::move(subuf.get());
|
||||
}
|
||||
|
||||
|
||||
} // end namesapce lld
|
|
@ -13,8 +13,11 @@
|
|||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/ArchiveLibraryFile.h"
|
||||
#include "lld/Core/SharedLibraryFile.h"
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/Driver/DarwinInputGraph.h"
|
||||
#include "lld/Driver/WrapperInputGraph.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
@ -22,6 +25,7 @@
|
|||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
|
@ -68,6 +72,33 @@ public:
|
|||
DarwinLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<File>>
|
||||
loadFile(MachOLinkingContext &ctx, StringRef path,
|
||||
raw_ostream &diag, bool wholeArchive, bool upwardDylib) {
|
||||
if (ctx.logInputFiles())
|
||||
diag << path << "\n";
|
||||
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
|
||||
DarwinLdDriver::getMemoryBuffer(ctx, path);
|
||||
if (std::error_code ec = mbOrErr.getError())
|
||||
return makeErrorFile(path, ec);
|
||||
std::vector<std::unique_ptr<File>> files;
|
||||
if (std::error_code ec = ctx.registry().loadFile(std::move(mbOrErr.get()), files))
|
||||
return makeErrorFile(path, ec);
|
||||
for (std::unique_ptr<File> &pf : files) {
|
||||
// If file is a dylib, inform LinkingContext about it.
|
||||
if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(pf.get())) {
|
||||
if (std::error_code ec = shl->parse())
|
||||
return makeErrorFile(path, ec);
|
||||
ctx.registerDylib(reinterpret_cast<mach_o::MachODylibFile*>(shl),
|
||||
upwardDylib);
|
||||
}
|
||||
}
|
||||
if (wholeArchive)
|
||||
return parseMemberFiles(files);
|
||||
return files;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Test may be running on Windows. Canonicalize the path
|
||||
|
@ -85,13 +116,12 @@ static std::string canonicalizePath(StringRef path) {
|
|||
|
||||
static void addFile(StringRef path, std::unique_ptr<InputGraph> &inputGraph,
|
||||
MachOLinkingContext &ctx, bool loadWholeArchive,
|
||||
bool upwardDylib) {
|
||||
auto node = llvm::make_unique<MachOFileNode>(path, ctx);
|
||||
if (loadWholeArchive)
|
||||
node->setLoadWholeArchive();
|
||||
if (upwardDylib)
|
||||
node->setUpwardDylib();
|
||||
inputGraph->addInputElement(std::move(node));
|
||||
bool upwardDylib, raw_ostream &diag) {
|
||||
std::vector<std::unique_ptr<File>> files =
|
||||
loadFile(ctx, path, diag, loadWholeArchive, upwardDylib);
|
||||
for (std::unique_ptr<File> &file : files)
|
||||
inputGraph->addInputElement(
|
||||
llvm::make_unique<WrapperNode>(std::move(file)));
|
||||
}
|
||||
|
||||
// Export lists are one symbol per line. Blank lines are ignored.
|
||||
|
@ -184,10 +214,10 @@ static std::error_code parseOrderFile(StringRef orderFilePath,
|
|||
// In this variant, the path is to a text file which contains a partial path
|
||||
// per line. The <dir> prefix is prepended to each partial path.
|
||||
//
|
||||
static std::error_code parseFileList(StringRef fileListPath,
|
||||
std::unique_ptr<InputGraph> &inputGraph,
|
||||
MachOLinkingContext &ctx, bool forceLoad,
|
||||
raw_ostream &diagnostics) {
|
||||
static std::error_code loadFileList(StringRef fileListPath,
|
||||
std::unique_ptr<InputGraph> &inputGraph,
|
||||
MachOLinkingContext &ctx, bool forceLoad,
|
||||
raw_ostream &diagnostics) {
|
||||
// If there is a comma, split off <dir>.
|
||||
std::pair<StringRef, StringRef> opt = fileListPath.split(',');
|
||||
StringRef filePath = opt.first;
|
||||
|
@ -222,7 +252,7 @@ static std::error_code parseFileList(StringRef fileListPath,
|
|||
if (ctx.testingFileUsage()) {
|
||||
diagnostics << "Found filelist entry " << canonicalizePath(path) << '\n';
|
||||
}
|
||||
addFile(path, inputGraph, ctx, forceLoad, false);
|
||||
addFile(path, inputGraph, ctx, forceLoad, false, diagnostics);
|
||||
buffer = lineAndRest.second;
|
||||
}
|
||||
return std::error_code();
|
||||
|
@ -237,6 +267,25 @@ static bool parseNumberBase16(StringRef numStr, uint64_t &baseAddress) {
|
|||
|
||||
namespace lld {
|
||||
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>>
|
||||
DarwinLdDriver::getMemoryBuffer(MachOLinkingContext &ctx, StringRef path) {
|
||||
ctx.addInputFileDependency(path);
|
||||
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
|
||||
MemoryBuffer::getFileOrSTDIN(path);
|
||||
if (std::error_code ec = mbOrErr.getError())
|
||||
return ec;
|
||||
std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get());
|
||||
|
||||
// If buffer contains a fat file, find required arch in fat buffer
|
||||
// and switch buffer to point to just that required slice.
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
if (ctx.sliceFromFatFile(*mb, offset, size))
|
||||
return MemoryBuffer::getFileSlice(path, size, offset);
|
||||
return std::move(mb);
|
||||
}
|
||||
|
||||
bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
|
||||
raw_ostream &diagnostics) {
|
||||
MachOLinkingContext ctx;
|
||||
|
@ -244,13 +293,6 @@ bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
|
|||
return false;
|
||||
if (ctx.doNothing())
|
||||
return true;
|
||||
|
||||
// Register possible input file parsers.
|
||||
ctx.registry().addSupportMachOObjects(ctx);
|
||||
ctx.registry().addSupportArchives(ctx.logInputFiles());
|
||||
ctx.registry().addSupportNativeObjects();
|
||||
ctx.registry().addSupportYamlFiles();
|
||||
|
||||
return link(ctx, diagnostics);
|
||||
}
|
||||
|
||||
|
@ -310,15 +352,15 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
}
|
||||
}
|
||||
// If no -arch specified, scan input files to find first non-fat .o file.
|
||||
if ((arch == MachOLinkingContext::arch_unknown)
|
||||
&& !parsedArgs->getLastArg(OPT_test_file_usage)) {
|
||||
if (arch == MachOLinkingContext::arch_unknown) {
|
||||
for (auto &inFile: parsedArgs->filtered(OPT_INPUT)) {
|
||||
// This is expensive because it opens and maps the file. But that is
|
||||
// ok because no -arch is rare.
|
||||
if (MachOLinkingContext::isThinObjectFile(inFile->getValue(), arch))
|
||||
break;
|
||||
}
|
||||
if (arch == MachOLinkingContext::arch_unknown) {
|
||||
if (arch == MachOLinkingContext::arch_unknown
|
||||
&& !parsedArgs->getLastArg(OPT_test_file_usage)) {
|
||||
// If no -arch and no options at all, print usage message.
|
||||
if (parsedArgs->size() == 0)
|
||||
table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
|
||||
|
@ -521,6 +563,13 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
}
|
||||
}
|
||||
|
||||
// Register possible input file parsers.
|
||||
if (!ctx.doNothing()) {
|
||||
ctx.registry().addSupportMachOObjects(ctx);
|
||||
ctx.registry().addSupportArchives(ctx.logInputFiles());
|
||||
ctx.registry().addSupportNativeObjects();
|
||||
ctx.registry().addSupportYamlFiles();
|
||||
}
|
||||
std::unique_ptr<InputGraph> inputGraph(new InputGraph());
|
||||
|
||||
// Now construct the set of library search directories, following ld64's
|
||||
|
@ -745,13 +794,13 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
default:
|
||||
continue;
|
||||
case OPT_INPUT:
|
||||
addFile(arg->getValue(), inputGraph, ctx, globalWholeArchive, false);
|
||||
addFile(arg->getValue(), inputGraph, ctx, globalWholeArchive, false, diagnostics);
|
||||
break;
|
||||
case OPT_upward_library:
|
||||
addFile(arg->getValue(), inputGraph, ctx, false, true);
|
||||
addFile(arg->getValue(), inputGraph, ctx, false, true, diagnostics);
|
||||
break;
|
||||
case OPT_force_load:
|
||||
addFile(arg->getValue(), inputGraph, ctx, true, false);
|
||||
addFile(arg->getValue(), inputGraph, ctx, true, false, diagnostics);
|
||||
break;
|
||||
case OPT_l:
|
||||
case OPT_upward_l:
|
||||
|
@ -765,7 +814,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
diagnostics << "Found " << (upward ? "upward " : " ") << "library "
|
||||
<< canonicalizePath(resolvedPath.get()) << '\n';
|
||||
}
|
||||
addFile(resolvedPath.get(), inputGraph, ctx, globalWholeArchive, upward);
|
||||
addFile(resolvedPath.get(), inputGraph, ctx, globalWholeArchive, upward, diagnostics);
|
||||
break;
|
||||
case OPT_framework:
|
||||
case OPT_upward_framework:
|
||||
|
@ -779,12 +828,12 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
diagnostics << "Found " << (upward ? "upward " : " ") << "framework "
|
||||
<< canonicalizePath(resolvedPath.get()) << '\n';
|
||||
}
|
||||
addFile(resolvedPath.get(), inputGraph, ctx, globalWholeArchive, upward);
|
||||
addFile(resolvedPath.get(), inputGraph, ctx, globalWholeArchive, upward, diagnostics);
|
||||
break;
|
||||
case OPT_filelist:
|
||||
if (std::error_code ec = parseFileList(arg->getValue(), inputGraph,
|
||||
ctx, globalWholeArchive,
|
||||
diagnostics)) {
|
||||
if (std::error_code ec = loadFileList(arg->getValue(), inputGraph,
|
||||
ctx, globalWholeArchive,
|
||||
diagnostics)) {
|
||||
diagnostics << "error: " << ec.message()
|
||||
<< ", processing '-filelist " << arg->getValue()
|
||||
<< "'\n";
|
||||
|
|
|
@ -49,13 +49,13 @@ FileVector parseMemberFiles(FileVector &files) {
|
|||
return members;
|
||||
}
|
||||
|
||||
FileVector parseFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
|
||||
FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> mb
|
||||
= MemoryBuffer::getFileOrSTDIN(path);
|
||||
if (std::error_code ec = mb.getError())
|
||||
return makeErrorFile(path, ec);
|
||||
std::vector<std::unique_ptr<File>> files;
|
||||
if (std::error_code ec = ctx.registry().parseFile(std::move(mb.get()), files))
|
||||
if (std::error_code ec = ctx.registry().loadFile(std::move(mb.get()), files))
|
||||
return makeErrorFile(path, ec);
|
||||
if (wholeArchive)
|
||||
return parseMemberFiles(files);
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/Driver/GnuLdInputGraph.h"
|
||||
#include "lld/Driver/WrapperInputGraph.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include "lld/ReaderWriter/LinkerScript.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
@ -172,16 +173,6 @@ bool GnuLdDriver::linkELF(int argc, const char *argv[],
|
|||
return false;
|
||||
if (!options)
|
||||
return true;
|
||||
|
||||
// Register possible input file parsers.
|
||||
options->registry().addSupportELFObjects(options->mergeCommonStrings(),
|
||||
options->targetHandler());
|
||||
options->registry().addSupportArchives(options->logInputFiles());
|
||||
options->registry().addSupportYamlFiles();
|
||||
options->registry().addSupportNativeObjects();
|
||||
if (options->allowLinkWithDynamicLibraries())
|
||||
options->registry().addSupportELFDynamicSharedObjects(
|
||||
options->useShlibUndefines(), options->targetHandler());
|
||||
return link(*options, diagnostics);
|
||||
}
|
||||
|
||||
|
@ -218,6 +209,23 @@ static bool isLinkerScript(StringRef path, raw_ostream &diag) {
|
|||
return magic == llvm::sys::fs::file_magic::unknown;
|
||||
}
|
||||
|
||||
static ErrorOr<StringRef>
|
||||
findFile(ELFLinkingContext &ctx, StringRef path, bool dashL) {
|
||||
// If the path was referred to by using a -l argument, let's search
|
||||
// for the file in the search path.
|
||||
if (dashL) {
|
||||
ErrorOr<StringRef> pathOrErr = ctx.searchLibrary(path);
|
||||
if (std::error_code ec = pathOrErr.getError())
|
||||
return make_dynamic_error_code(
|
||||
Twine("Unable to find library -l") + path + ": " + ec.message());
|
||||
path = pathOrErr->str();
|
||||
}
|
||||
if (!llvm::sys::fs::exists(path))
|
||||
return make_dynamic_error_code(
|
||||
Twine("lld: cannot find file ") + path);
|
||||
return path;
|
||||
}
|
||||
|
||||
static bool isPathUnderSysroot(StringRef sysroot, StringRef path) {
|
||||
if (sysroot.empty())
|
||||
return false;
|
||||
|
@ -234,8 +242,6 @@ evaluateLinkerScript(ELFLinkingContext &ctx, InputGraph *inputGraph,
|
|||
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();
|
||||
|
@ -253,13 +259,26 @@ evaluateLinkerScript(ELFLinkingContext &ctx, InputGraph *inputGraph,
|
|||
int numfiles = 0;
|
||||
for (const script::Path &path : group->getPaths()) {
|
||||
// TODO : Propagate Set WholeArchive/dashlPrefix
|
||||
ELFFileNode::Attributes attr;
|
||||
ELFLinkingContext::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));
|
||||
|
||||
ErrorOr<StringRef> pathOrErr = path._isDashlPrefix
|
||||
? ctx.searchLibrary(path._path) : ctx.searchFile(path._path, sysroot);
|
||||
if (std::error_code ec = pathOrErr.getError())
|
||||
return make_dynamic_error_code(
|
||||
Twine("Unable to find file ") + path._path + ": " + ec.message());
|
||||
|
||||
std::vector<std::unique_ptr<File>> files
|
||||
= loadFile(ctx, pathOrErr.get(), false);
|
||||
for (std::unique_ptr<File> &file : files) {
|
||||
if (ctx.logInputFiles())
|
||||
diag << file->path() << "\n";
|
||||
inputGraph->addInputElement(
|
||||
std::unique_ptr<InputElement>(new WrapperNode(std::move(file))));
|
||||
++numfiles;
|
||||
}
|
||||
}
|
||||
inputGraph->addInputElement(llvm::make_unique<GroupEnd>(numfiles));
|
||||
}
|
||||
|
@ -341,7 +360,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
std::stack<int> groupStack;
|
||||
int numfiles = 0;
|
||||
|
||||
ELFFileNode::Attributes attributes;
|
||||
ELFLinkingContext::Attributes attributes;
|
||||
|
||||
bool _outputOptionSet = false;
|
||||
|
||||
|
@ -379,7 +398,6 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
ctx->setPrintRemainingUndefines(false);
|
||||
ctx->setAllowRemainingUndefines(true);
|
||||
break;
|
||||
|
||||
case OPT_static:
|
||||
ctx->setOutputELFType(llvm::ELF::ET_EXEC);
|
||||
ctx->setIsStaticExecutable(true);
|
||||
|
@ -415,6 +433,37 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
}
|
||||
}
|
||||
|
||||
for (auto inputArg : *parsedArgs) {
|
||||
switch (inputArg->getOption().getID()) {
|
||||
case OPT_merge_strings:
|
||||
ctx->setMergeCommonStrings(true);
|
||||
break;
|
||||
case OPT_t:
|
||||
ctx->setLogInputFiles(true);
|
||||
break;
|
||||
case OPT_use_shlib_undefs:
|
||||
ctx->setUseShlibUndefines(true);
|
||||
break;
|
||||
case OPT_no_allow_shlib_undefs:
|
||||
ctx->setAllowShlibUndefines(false);
|
||||
break;
|
||||
case OPT_allow_shlib_undefs:
|
||||
ctx->setAllowShlibUndefines(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Register possible input file parsers.
|
||||
ctx->registry().addSupportELFObjects(
|
||||
ctx->mergeCommonStrings(),
|
||||
ctx->targetHandler());
|
||||
ctx->registry().addSupportArchives(ctx->logInputFiles());
|
||||
ctx->registry().addSupportYamlFiles();
|
||||
ctx->registry().addSupportNativeObjects();
|
||||
if (ctx->allowLinkWithDynamicLibraries())
|
||||
ctx->registry().addSupportELFDynamicSharedObjects(
|
||||
ctx->useShlibUndefines(), ctx->targetHandler());
|
||||
|
||||
// Process all the arguments and create Input Elements
|
||||
for (auto inputArg : *parsedArgs) {
|
||||
switch (inputArg->getOption().getID()) {
|
||||
|
@ -438,26 +487,6 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
ctx->setExportDynamic(true);
|
||||
break;
|
||||
|
||||
case OPT_merge_strings:
|
||||
ctx->setMergeCommonStrings(true);
|
||||
break;
|
||||
|
||||
case OPT_t:
|
||||
ctx->setLogInputFiles(true);
|
||||
break;
|
||||
|
||||
case OPT_no_allow_shlib_undefs:
|
||||
ctx->setAllowShlibUndefines(false);
|
||||
break;
|
||||
|
||||
case OPT_allow_shlib_undefs:
|
||||
ctx->setAllowShlibUndefines(true);
|
||||
break;
|
||||
|
||||
case OPT_use_shlib_undefs:
|
||||
ctx->setUseShlibUndefines(true);
|
||||
break;
|
||||
|
||||
case OPT_allow_multiple_definition:
|
||||
ctx->setAllowDuplicates(true);
|
||||
break;
|
||||
|
@ -560,25 +589,19 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
bool dashL = (inputArg->getOption().getID() == OPT_l);
|
||||
attributes.setDashlPrefix(dashL);
|
||||
StringRef path = inputArg->getValue();
|
||||
std::string realpath = path;
|
||||
|
||||
// If the path was referred to by using a -l argument, let's search
|
||||
// for the file in the search path.
|
||||
if (dashL) {
|
||||
ErrorOr<StringRef> pathOrErr = ctx->searchLibrary(path);
|
||||
if (!pathOrErr) {
|
||||
diagnostics << " Unable to find library -l" << path << "\n";
|
||||
return false;
|
||||
}
|
||||
realpath = pathOrErr->str();
|
||||
}
|
||||
if (!llvm::sys::fs::exists(realpath)) {
|
||||
diagnostics << "lld: cannot find file " << path << "\n";
|
||||
ErrorOr<StringRef> pathOrErr = findFile(*ctx, path, dashL);
|
||||
if (std::error_code ec = pathOrErr.getError()) {
|
||||
diagnostics << ec.message() << "\n";
|
||||
return false;
|
||||
}
|
||||
std::string realpath = pathOrErr.get();
|
||||
|
||||
bool isScript =
|
||||
(!path.endswith(".objtxt") && isLinkerScript(realpath, diagnostics));
|
||||
if (isScript) {
|
||||
if (ctx->logInputFiles())
|
||||
diagnostics << path << "\n";
|
||||
std::error_code ec = evaluateLinkerScript(
|
||||
*ctx, inputGraph.get(), realpath, diagnostics);
|
||||
if (ec) {
|
||||
|
@ -588,9 +611,15 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
}
|
||||
break;
|
||||
}
|
||||
++numfiles;
|
||||
inputGraph->addInputElement(
|
||||
llvm::make_unique<ELFFileNode>(*ctx, path, attributes));
|
||||
std::vector<std::unique_ptr<File>> files
|
||||
= loadFile(*ctx, realpath, attributes._isWholeArchive);
|
||||
for (std::unique_ptr<File> &file : files) {
|
||||
if (ctx->logInputFiles())
|
||||
diagnostics << file->path() << "\n";
|
||||
inputGraph->addInputElement(
|
||||
std::unique_ptr<InputElement>(new WrapperNode(std::move(file))));
|
||||
}
|
||||
numfiles += files.size();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
//===- 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/Errc.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
using namespace lld;
|
||||
|
||||
llvm::ErrorOr<StringRef> ELFFileNode::getPath(const LinkingContext &) const {
|
||||
if (_attributes._isDashlPrefix)
|
||||
return _elfLinkingContext.searchLibrary(_path);
|
||||
return _elfLinkingContext.searchFile(_path, _attributes._isSysRooted);
|
||||
}
|
||||
|
||||
std::string ELFFileNode::errStr(std::error_code errc) {
|
||||
if (errc == llvm::errc::no_such_file_or_directory) {
|
||||
if (_attributes._isDashlPrefix)
|
||||
return (Twine("Unable to find library -l") + _path).str();
|
||||
return (Twine("Unable to find file ") + _path).str();
|
||||
}
|
||||
return FileNode::errStr(errc);
|
||||
}
|
||||
|
||||
/// \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;
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
|
||||
MemoryBuffer::getFileOrSTDIN(*filePath);
|
||||
if (std::error_code ec = mb.getError())
|
||||
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(
|
||||
std::move(mb.get()), 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(std::move(mb.get()), _files);
|
||||
}
|
|
@ -14,8 +14,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/Driver/WinLinkInputGraph.h"
|
||||
#include "lld/Driver/WinLinkModuleDef.h"
|
||||
#include "lld/Driver/WrapperInputGraph.h"
|
||||
#include "lld/ReaderWriter/PECOFFLinkingContext.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
@ -800,13 +800,11 @@ parseArgs(int argc, const char **argv, PECOFFLinkingContext &ctx,
|
|||
|
||||
// Returns true if the given file node has already been added to the input
|
||||
// graph.
|
||||
static bool hasLibrary(const PECOFFLinkingContext &ctx, FileNode *fileNode) {
|
||||
ErrorOr<StringRef> path = fileNode->getPath(ctx);
|
||||
if (!path)
|
||||
return false;
|
||||
static bool hasLibrary(const PECOFFLinkingContext &ctx, File *file) {
|
||||
StringRef path = file->path();
|
||||
for (std::unique_ptr<InputElement> &p : ctx.getInputGraph().inputElements())
|
||||
if (auto *f = dyn_cast<FileNode>(p.get()))
|
||||
if (*path == *f->getPath(ctx))
|
||||
if (*f->getPath(ctx) == path)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -838,6 +836,16 @@ static bool maybeRunLibCommand(int argc, const char **argv, raw_ostream &diag) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// \brief Parse the input file to lld::File.
|
||||
void addFiles(PECOFFLinkingContext &ctx, StringRef path, raw_ostream &diag,
|
||||
std::vector<std::unique_ptr<File>> &files) {
|
||||
for (std::unique_ptr<File> &file : loadFile(ctx, path, false)) {
|
||||
if (ctx.logInputFiles())
|
||||
diag << file->path() << "\n";
|
||||
files.push_back(std::move(file));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Main driver
|
||||
//
|
||||
|
@ -847,6 +855,12 @@ bool WinLinkDriver::linkPECOFF(int argc, const char **argv, raw_ostream &diag) {
|
|||
return true;
|
||||
|
||||
PECOFFLinkingContext ctx;
|
||||
ctx.registry().addSupportCOFFObjects(ctx);
|
||||
ctx.registry().addSupportCOFFImportLibraries(ctx);
|
||||
ctx.registry().addSupportArchives(ctx.logInputFiles());
|
||||
ctx.registry().addSupportNativeObjects();
|
||||
ctx.registry().addSupportYamlFiles();
|
||||
|
||||
std::vector<const char *> newargv = processLinkEnv(ctx, argc, argv);
|
||||
processLibEnv(ctx);
|
||||
if (!parse(newargv.size() - 1, &newargv[0], ctx, diag))
|
||||
|
@ -857,13 +871,6 @@ bool WinLinkDriver::linkPECOFF(int argc, const char **argv, raw_ostream &diag) {
|
|||
if (!createSideBySideManifestFile(ctx, diag))
|
||||
return false;
|
||||
|
||||
// Register possible input file parsers.
|
||||
ctx.registry().addSupportCOFFObjects(ctx);
|
||||
ctx.registry().addSupportCOFFImportLibraries(ctx);
|
||||
ctx.registry().addSupportArchives(ctx.logInputFiles());
|
||||
ctx.registry().addSupportNativeObjects();
|
||||
ctx.registry().addSupportYamlFiles();
|
||||
|
||||
return link(ctx, diag);
|
||||
}
|
||||
|
||||
|
@ -884,8 +891,8 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
|||
return false;
|
||||
|
||||
// The list of input files.
|
||||
std::vector<std::unique_ptr<FileNode> > files;
|
||||
std::vector<std::unique_ptr<FileNode> > libraries;
|
||||
std::vector<std::unique_ptr<File>> files;
|
||||
std::vector<std::unique_ptr<File>> libraries;
|
||||
|
||||
// Handle /help
|
||||
if (parsedArgs->getLastArg(OPT_help)) {
|
||||
|
@ -1363,11 +1370,9 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
|||
for (StringRef path : inputFiles) {
|
||||
path = ctx.allocate(path);
|
||||
if (isLibraryFile(path)) {
|
||||
libraries.push_back(std::unique_ptr<FileNode>(
|
||||
new PECOFFFileNode(ctx, getLibraryPath(ctx, path))));
|
||||
addFiles(ctx, getLibraryPath(ctx, path), diag, libraries);
|
||||
} else {
|
||||
files.push_back(std::unique_ptr<FileNode>(
|
||||
new PECOFFFileNode(ctx, getObjectPath(ctx, path))));
|
||||
addFiles(ctx, getObjectPath(ctx, path), diag, files);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1389,8 +1394,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
|||
if (!ctx.getNoDefaultLibAll())
|
||||
for (const StringRef path : defaultLibs)
|
||||
if (!ctx.hasNoDefaultLib(path))
|
||||
libraries.push_back(std::unique_ptr<FileNode>(
|
||||
new PECOFFFileNode(ctx, getLibraryPath(ctx, path.lower()))));
|
||||
addFiles(ctx, getLibraryPath(ctx, path.lower()), diag, libraries);
|
||||
|
||||
if (files.empty() && !isReadingDirectiveSection) {
|
||||
diag << "No input files\n";
|
||||
|
@ -1401,18 +1405,19 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
|||
// constructed by replacing an extension of the first input file
|
||||
// with ".exe".
|
||||
if (ctx.outputPath().empty()) {
|
||||
StringRef path = *cast<FileNode>(&*files[0])->getPath(ctx);
|
||||
StringRef path = files[0]->path();
|
||||
ctx.setOutputPath(replaceExtension(ctx, path, ".exe"));
|
||||
}
|
||||
|
||||
// Add the input files to the input graph.
|
||||
if (!ctx.hasInputGraph())
|
||||
ctx.setInputGraph(std::unique_ptr<InputGraph>(new InputGraph()));
|
||||
for (std::unique_ptr<FileNode> &file : files) {
|
||||
for (std::unique_ptr<File> &file : files) {
|
||||
if (isReadingDirectiveSection)
|
||||
if (file->parse(ctx, diag))
|
||||
if (file->parse())
|
||||
return false;
|
||||
ctx.getInputGraph().addInputElement(std::move(file));
|
||||
ctx.getInputGraph().addInputElement(
|
||||
std::unique_ptr<InputElement>(new WrapperNode(std::move(file))));
|
||||
}
|
||||
|
||||
// Add the library group to the input graph.
|
||||
|
@ -1427,12 +1432,13 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
|||
}
|
||||
|
||||
// Add the library files to the library group.
|
||||
for (std::unique_ptr<FileNode> &lib : libraries) {
|
||||
if (!hasLibrary(ctx, lib.get())) {
|
||||
for (std::unique_ptr<File> &file : libraries) {
|
||||
if (!hasLibrary(ctx, file.get())) {
|
||||
if (isReadingDirectiveSection)
|
||||
if (lib->parse(ctx, diag))
|
||||
if (file->parse())
|
||||
return false;
|
||||
ctx.addLibraryFile(std::move(lib));
|
||||
ctx.addLibraryFile(
|
||||
std::unique_ptr<FileNode>(new WrapperNode(std::move(file))));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
//===- lib/Driver/WinLinkInputGraph.cpp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/WinLinkInputGraph.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
/// \brief Parse the input file to lld::File.
|
||||
std::error_code PECOFFFileNode::parse(const LinkingContext &ctx,
|
||||
raw_ostream &diagnostics) {
|
||||
if (_parsed)
|
||||
return std::error_code();
|
||||
_parsed = true;
|
||||
ErrorOr<StringRef> filePath = getPath(ctx);
|
||||
if (std::error_code ec = filePath.getError()) {
|
||||
diagnostics << "File not found: " << _path << "\n";
|
||||
return ec;
|
||||
}
|
||||
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
|
||||
MemoryBuffer::getFileOrSTDIN(*filePath);
|
||||
if (std::error_code ec = mb.getError()) {
|
||||
diagnostics << "Cannot open file: " << *filePath << "\n";
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (ctx.logInputFiles())
|
||||
diagnostics << *filePath << "\n";
|
||||
|
||||
return ctx.registry().parseFile(std::move(mb.get()), _files);
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
|
@ -40,13 +40,15 @@ void RoundTripNativePass::perform(std::unique_ptr<MutableFile> &mergedFile) {
|
|||
if (!mb)
|
||||
return;
|
||||
|
||||
std::error_code ec = _context.registry().parseFile(
|
||||
std::error_code ec = _context.registry().loadFile(
|
||||
std::move(mb.get()), _nativeFile);
|
||||
if (ec) {
|
||||
// Note: we need a way for Passes to report errors.
|
||||
llvm_unreachable("native reader not registered or read error");
|
||||
}
|
||||
File *objFile = _nativeFile[0].get();
|
||||
if (objFile->parse())
|
||||
llvm_unreachable("native reader parse error");
|
||||
mergedFile.reset(new SimpleFileWrapper(_context, *objFile));
|
||||
|
||||
llvm::sys::fs::remove(tmpNativeFile.str());
|
||||
|
|
|
@ -40,13 +40,15 @@ void RoundTripYAMLPass::perform(std::unique_ptr<MutableFile> &mergedFile) {
|
|||
if (!mb)
|
||||
return;
|
||||
|
||||
std::error_code ec = _context.registry().parseFile(
|
||||
std::error_code ec = _context.registry().loadFile(
|
||||
std::move(mb.get()), _yamlFile);
|
||||
if (ec) {
|
||||
// Note: we need a way for Passes to report errors.
|
||||
llvm_unreachable("yaml reader not registered or read error");
|
||||
}
|
||||
File *objFile = _yamlFile[0].get();
|
||||
if (objFile->parse())
|
||||
llvm_unreachable("native reader parse error");
|
||||
mergedFile.reset(new SimpleFileWrapper(_context, *objFile));
|
||||
llvm::sys::fs::remove(tmpYAMLFile.str());
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
std::size_t maxAlignment =
|
||||
1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));
|
||||
auto f =
|
||||
|
@ -72,8 +72,8 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
std::size_t maxAlignment =
|
||||
1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));
|
||||
auto f =
|
||||
|
|
|
@ -49,12 +49,12 @@ public:
|
|||
_flagMerger(flagMerger) {}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®istry,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®istry,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
auto &hdr = *elfHeader(*mb);
|
||||
if (std::error_code ec = _flagMerger.merge(hdr.getFileClass(), hdr.e_flags))
|
||||
return ec;
|
||||
return BaseReaderType::parseFile(std::move(mb), registry, result);
|
||||
return BaseReaderType::loadFile(std::move(mb), registry, result);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -72,12 +72,12 @@ public:
|
|||
_flagMerger(flagMerger) {}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®istry,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®istry,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
auto &hdr = *elfHeader(*mb);
|
||||
if (std::error_code ec = _flagMerger.merge(hdr.getFileClass(), hdr.e_flags))
|
||||
return ec;
|
||||
return BaseReaderType::parseFile(std::move(mb), registry, result);
|
||||
return BaseReaderType::loadFile(std::move(mb), registry, result);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -67,7 +67,9 @@ public:
|
|||
|
||||
/// \brief parse each member
|
||||
std::error_code
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
|
||||
if (std::error_code ec = parse())
|
||||
return ec;
|
||||
for (auto mf = _archive->child_begin(), me = _archive->child_end();
|
||||
mf != me; ++mf) {
|
||||
std::unique_ptr<File> file;
|
||||
|
@ -152,9 +154,12 @@ private:
|
|||
mb.getBuffer(), memberPath, false));
|
||||
|
||||
std::vector<std::unique_ptr<File>> files;
|
||||
_registry.parseFile(std::move(memberMB), files);
|
||||
if (std::error_code ec = _registry.loadFile(std::move(memberMB), files))
|
||||
return ec;
|
||||
assert(files.size() == 1);
|
||||
result = std::move(files[0]);
|
||||
if (std::error_code ec = result->parse())
|
||||
return ec;
|
||||
|
||||
// The memory buffer is co-owned by the archive file and the children,
|
||||
// so that the bufffer is deallocated when all the members are destructed.
|
||||
|
@ -232,8 +237,8 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
StringRef path = mb->getBufferIdentifier();
|
||||
std::unique_ptr<FileArchive> file(
|
||||
new FileArchive(std::move(mb), reg, path, _logLoading));
|
||||
|
|
|
@ -91,7 +91,7 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
#include "File.h"
|
||||
#include "MachONormalizedFile.h"
|
||||
#include "MachOPasses.h"
|
||||
#include "lld/Core/ArchiveLibraryFile.h"
|
||||
#include "lld/Core/PassManager.h"
|
||||
#include "lld/Driver/DarwinInputGraph.h"
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/Passes/LayoutPass.h"
|
||||
#include "lld/Passes/RoundTripYAMLPass.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
|
@ -605,20 +606,19 @@ Writer &MachOLinkingContext::writer() const {
|
|||
}
|
||||
|
||||
MachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) {
|
||||
std::unique_ptr<MachOFileNode> node(new MachOFileNode(path, *this));
|
||||
std::error_code ec = node->parse(*this, llvm::errs());
|
||||
if (ec)
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
|
||||
DarwinLdDriver::getMemoryBuffer(*this, path);
|
||||
if (mbOrErr.getError())
|
||||
return nullptr;
|
||||
|
||||
assert(node->files().size() == 1 && "expected one file in dylib");
|
||||
// lld::File object is owned by MachOFileNode object. This method returns
|
||||
// an unowned pointer to the lld::File object.
|
||||
MachODylibFile* result = reinterpret_cast<MachODylibFile*>(
|
||||
node->files().front().get());
|
||||
|
||||
std::vector<std::unique_ptr<File>> files;
|
||||
if (registry().loadFile(std::move(mbOrErr.get()), files))
|
||||
return nullptr;
|
||||
assert(files.size() == 1 && "expected one file in dylib");
|
||||
files[0]->parse();
|
||||
MachODylibFile* result = reinterpret_cast<MachODylibFile*>(files[0].get());
|
||||
// Node object now owned by _indirectDylibs vector.
|
||||
_indirectDylibs.push_back(std::move(node));
|
||||
|
||||
_indirectDylibs.push_back(std::move(files[0]));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -527,8 +527,8 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®istry,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®istry,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
auto *file = new MachOFile(std::move(mb), &_ctx);
|
||||
result.push_back(std::unique_ptr<MachOFile>(file));
|
||||
return std::error_code();
|
||||
|
@ -554,8 +554,8 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®istry,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry ®istry,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
auto *file = new MachODylibFile(std::move(mb), &_ctx);
|
||||
result.push_back(std::unique_ptr<MachODylibFile>(file));
|
||||
return std::error_code();
|
||||
|
@ -580,4 +580,3 @@ void Registry::addSupportMachOObjects(MachOLinkingContext &ctx) {
|
|||
|
||||
|
||||
} // namespace lld
|
||||
|
||||
|
|
|
@ -999,8 +999,8 @@ public:
|
|||
}
|
||||
|
||||
virtual std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
auto *file = new lld::native::File(std::move(mb));
|
||||
result.push_back(std::unique_ptr<File>(file));
|
||||
return std::error_code();
|
||||
|
|
|
@ -88,7 +88,7 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
|
|
|
@ -1077,8 +1077,8 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
// Parse the memory buffer as PECOFF file.
|
||||
auto *file = new FileCOFF(std::move(mb), _ctx);
|
||||
result.push_back(std::unique_ptr<File>(file));
|
||||
|
|
|
@ -354,7 +354,7 @@ private:
|
|||
|
||||
class COFFImportLibraryReader : public Reader {
|
||||
public:
|
||||
COFFImportLibraryReader(MachineTypes machine) : _machine(machine) {}
|
||||
COFFImportLibraryReader(PECOFFLinkingContext &ctx) : _ctx(ctx) {}
|
||||
|
||||
bool canParse(file_magic magic, StringRef,
|
||||
const MemoryBuffer &mb) const override {
|
||||
|
@ -364,22 +364,21 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File> > &result) const override {
|
||||
auto *file = new FileImportLibrary(std::move(mb), _machine);
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File> > &result) const override {
|
||||
auto *file = new FileImportLibrary(std::move(mb), _ctx.getMachineType());
|
||||
result.push_back(std::unique_ptr<File>(file));
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
private:
|
||||
MachineTypes _machine;
|
||||
PECOFFLinkingContext &_ctx;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
void Registry::addSupportCOFFImportLibraries(PECOFFLinkingContext &ctx) {
|
||||
MachineTypes machine = ctx.getMachineType();
|
||||
add(llvm::make_unique<COFFImportLibraryReader>(machine));
|
||||
add(llvm::make_unique<COFFImportLibraryReader>(ctx));
|
||||
}
|
||||
|
||||
} // end namespace lld
|
||||
|
|
|
@ -30,8 +30,8 @@ void Registry::add(std::unique_ptr<YamlIOTaggedDocumentHandler> handler) {
|
|||
}
|
||||
|
||||
std::error_code
|
||||
Registry::parseFile(std::unique_ptr<MemoryBuffer> mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
Registry::loadFile(std::unique_ptr<MemoryBuffer> mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
// Get file type.
|
||||
StringRef content(mb->getBufferStart(), mb->getBufferSize());
|
||||
llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(content);
|
||||
|
@ -42,11 +42,8 @@ Registry::parseFile(std::unique_ptr<MemoryBuffer> mb,
|
|||
for (const std::unique_ptr<Reader> &reader : _readers) {
|
||||
if (!reader->canParse(fileType, extension, *mb))
|
||||
continue;
|
||||
if (std::error_code ec = reader->parseFile(std::move(mb), *this, result))
|
||||
if (std::error_code ec = reader->loadFile(std::move(mb), *this, result))
|
||||
return ec;
|
||||
for (std::unique_ptr<File> &file : result)
|
||||
if (std::error_code ec = file->parse())
|
||||
return ec;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
|
|
|
@ -648,7 +648,7 @@ template <> struct MappingTraits<const lld::File *> {
|
|||
}
|
||||
|
||||
virtual std::error_code
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
|
||||
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
|
@ -1325,8 +1325,8 @@ public:
|
|||
}
|
||||
|
||||
std::error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
// Create YAML Input Reader.
|
||||
YamlContext yamlContext;
|
||||
yamlContext._registry = &_registry;
|
||||
|
@ -1343,7 +1343,7 @@ public:
|
|||
|
||||
std::shared_ptr<MemoryBuffer> smb(mb.release());
|
||||
for (const File *file : createdFiles) {
|
||||
// Note: parseFile() should return vector of *const* File
|
||||
// Note: loadFile() should return vector of *const* File
|
||||
File *f = const_cast<File *>(file);
|
||||
f->setLastError(std::error_code());
|
||||
f->setSharedMemoryBuffer(smb);
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
RUN: lld -flavor gnu -target x86_64-linux -L%p/../elf/Inputs -lfnarchive \
|
||||
RUN: --output-filetype=yaml --noinhibit-exec 2> %t.err
|
||||
RUN: FileCheck %s < %t.err
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64-linux -L%p/../elf/Inputs --whole-archive \
|
||||
RUN: -lfnarchive --output-filetype=yaml --noinhibit-exec 2> %t1.err
|
||||
RUN: FileCheck %s -check-prefix="WHOLEARCHIVE" < %t1.err
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64-linux -L%p/../elf/Inputs --whole-archive \
|
||||
RUN: --as-needed -lfnarchive --output-filetype=yaml --noinhibit-exec 2> %t2.err
|
||||
RUN: FileCheck %s -check-prefix="ASNEEDED" < %t2.err
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64-linux --sysroot=%p/../elf -L=/Inputs \
|
||||
RUN: -lfnarchive --output-filetype=yaml --noinhibit-exec 2> %t3.err
|
||||
RUN: FileCheck -check-prefix="SYSROOT" %s < %t3.err
|
||||
|
||||
CHECK: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
|
||||
CHECK: Type : ELF File
|
||||
CHECK: Attributes :
|
||||
CHECK: - wholeArchive : false
|
||||
CHECK: - asNeeded : false
|
||||
|
||||
WHOLEARCHIVE: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
|
||||
WHOLEARCHIVE: Type : ELF File
|
||||
WHOLEARCHIVE: Attributes :
|
||||
WHOLEARCHIVE: - wholeArchive : true
|
||||
WHOLEARCHIVE: - asNeeded : false
|
||||
|
||||
ASNEEDED: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
|
||||
ASNEEDED: Type : ELF File
|
||||
ASNEEDED: Attributes :
|
||||
ASNEEDED: - wholeArchive : true
|
||||
ASNEEDED: - asNeeded : true
|
||||
|
||||
SYSROOT: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
|
||||
SYSROOT: Type : ELF File
|
||||
SYSROOT: Attributes :
|
||||
SYSROOT: - wholeArchive : false
|
||||
SYSROOT: - asNeeded : false
|
|
@ -698,10 +698,9 @@ TEST_F(WinLinkParserTest, Ignore) {
|
|||
// compatibility with link.exe.
|
||||
EXPECT_TRUE(parse("link.exe", "/nologo", "/errorreport:prompt",
|
||||
"/incremental", "/incremental:no", "/delay:unload",
|
||||
"/disallowlib:foo", "/pdbaltpath:bar", "/verbose",
|
||||
"/verbose:icf", "/wx", "/wx:no", "/tlbid:1",
|
||||
"/tlbout:foo", "/idlout:foo", "/ignore:4000",
|
||||
"/ignoreidl", "/implib:foo", "/safeseh",
|
||||
"/disallowlib:foo", "/pdbaltpath:bar",
|
||||
"/wx", "/wx:no", "/tlbid:1", "/tlbout:foo", "/idlout:foo",
|
||||
"/ignore:4000", "/ignoreidl", "/implib:foo", "/safeseh",
|
||||
"/safeseh:no", "/functionpadmin", "/maxilksize:1024",
|
||||
"a.obj", nullptr));
|
||||
EXPECT_EQ("", errorMessage());
|
||||
|
|
Loading…
Reference in New Issue