summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/Core/Resolver.cpp55
-rw-r--r--lld/lib/Core/SymbolTable.cpp10
-rw-r--r--lld/lib/Core/TargetInfo.cpp43
-rw-r--r--lld/lib/Driver/CMakeLists.txt8
-rw-r--r--lld/lib/Driver/CoreDriver.cpp158
-rw-r--r--lld/lib/Driver/CoreOptions.td25
-rw-r--r--lld/lib/Driver/DarwinLdDriver.cpp197
-rw-r--r--lld/lib/Driver/DarwinOptions.td30
-rw-r--r--lld/lib/Driver/Driver.cpp78
-rw-r--r--lld/lib/Driver/Drivers.cpp303
-rw-r--r--lld/lib/Driver/GnuLdDriver.cpp241
-rw-r--r--lld/lib/Driver/LDOptions.td39
-rw-r--r--lld/lib/Driver/LinkerInvocation.cpp98
-rw-r--r--lld/lib/Driver/UniversalDriver.cpp109
-rw-r--r--lld/lib/Passes/LayoutPass.cpp24
-rw-r--r--lld/lib/ReaderWriter/CMakeLists.txt1
-rw-r--r--lld/lib/ReaderWriter/CoreTargetInfo.cpp395
-rw-r--r--lld/lib/ReaderWriter/ELF/Atoms.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/DefaultLayout.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h1
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp148
-rw-r--r--lld/lib/ReaderWriter/ELF/ExecutableAtoms.h1
-rw-r--r--lld/lib/ReaderWriter/ELF/ExecutableWriter.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/File.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/HeaderChunks.h7
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp3
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp4
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h10
-rw-r--r--lld/lib/ReaderWriter/ELF/OutputELFWriter.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp36
-rw-r--r--lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h8
-rw-r--r--lld/lib/ReaderWriter/ELF/Reader.cpp17
-rw-r--r--lld/lib/ReaderWriter/ELF/SectionChunks.h6
-rw-r--r--lld/lib/ReaderWriter/ELF/TargetHandler.h1
-rw-r--r--lld/lib/ReaderWriter/ELF/Writer.cpp86
-rw-r--r--lld/lib/ReaderWriter/ELF/Writer.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp36
-rw-r--r--lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h7
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp27
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h14
-rw-r--r--lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp8
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOFormat.hpp6
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp247
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp18
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.h3
-rw-r--r--lld/lib/ReaderWriter/MachO/StubsPass.hpp21
-rw-r--r--lld/lib/ReaderWriter/MachO/WriterMachO.cpp69
-rw-r--r--lld/lib/ReaderWriter/Native/ReaderNative.cpp4
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp4
-rw-r--r--lld/lib/ReaderWriter/Reader.cpp4
-rw-r--r--lld/lib/ReaderWriter/ReaderArchive.cpp31
-rw-r--r--lld/lib/ReaderWriter/ReaderLinkerScript.cpp10
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp40
54 files changed, 1939 insertions, 769 deletions
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index 6d3880f31d3..d5e747fc0de 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -10,7 +10,6 @@
#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
#include "lld/Core/InputFiles.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/SymbolTable.h"
@@ -129,7 +128,7 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
// tell symbol table
_symbolTable.add(atom);
- if (_targetInfo.getLinkerOptions()._deadStrip) {
+ if (_targetInfo.deadStrip()) {
// add to set of dead-strip-roots, all symbols that
// the compiler marks as don't strip
if (atom.deadStrip() == DefinedAtom::deadStripNever)
@@ -182,11 +181,11 @@ void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
// ask symbol table if any definitionUndefined atoms still exist
// if so, keep searching libraries until no more atoms being added
void Resolver::resolveUndefines() {
- const bool searchArchives = _targetInfo.getLinkerOptions().
- _searchArchivesToOverrideTentativeDefinitions;
- const bool searchSharedLibs = _targetInfo.getLinkerOptions().
- _searchSharedLibrariesToOverrideTentativeDefinitions;
-
+ const bool searchArchives =
+ _targetInfo.searchArchivesToOverrideTentativeDefinitions();
+ const bool searchSharedLibs =
+ _targetInfo.searchSharedLibrariesToOverrideTentativeDefinitions();
+
// keep looping until no more undefines were added in last loop
unsigned int undefineGenCount = 0xFFFFFFFF;
while (undefineGenCount != _symbolTable.size()) {
@@ -259,14 +258,14 @@ void Resolver::markLive(const Atom &atom) {
// remove all atoms not actually used
void Resolver::deadStripOptimize() {
// only do this optimization with -dead_strip
- if (!_targetInfo.getLinkerOptions()._deadStrip)
+ if (!_targetInfo.deadStrip())
return;
// clear liveness on all atoms
_liveAtoms.clear();
// By default, shared libraries are built with all globals as dead strip roots
- if (_targetInfo.getLinkerOptions()._globalsAreDeadStripRoots) {
+ if (_targetInfo.globalsAreDeadStripRoots()) {
for ( const Atom *atom : _atoms ) {
const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom);
if (defAtom == nullptr)
@@ -277,7 +276,7 @@ void Resolver::deadStripOptimize() {
}
// Or, use list of names that are dead stip roots.
- for (const StringRef &name : _targetInfo.getLinkerOptions()._deadStripRoots) {
+ for (const StringRef &name : _targetInfo.deadStripRoots()) {
const Atom *symAtom = _symbolTable.findByName(name);
assert(symAtom->definition() != Atom::definitionUndefined);
_deadStripRoots.insert(symAtom);
@@ -295,15 +294,15 @@ void Resolver::deadStripOptimize() {
// error out if some undefines remain
-void Resolver::checkUndefines(bool final) {
+bool Resolver::checkUndefines(bool final) {
// when using LTO, undefines are checked after bitcode is optimized
if (_haveLLVMObjs && !final)
- return;
+ return false;
// build vector of remaining undefined symbols
std::vector<const UndefinedAtom *> undefinedAtoms;
_symbolTable.undefines(undefinedAtoms);
- if (_targetInfo.getLinkerOptions()._deadStrip) {
+ if (_targetInfo.deadStrip()) {
// When dead code stripping, we don't care if dead atoms are undefined.
undefinedAtoms.erase(std::remove_if(
undefinedAtoms.begin(), undefinedAtoms.end(),
@@ -311,21 +310,25 @@ void Resolver::checkUndefines(bool final) {
}
// error message about missing symbols
- if (!undefinedAtoms.empty() &&
- (!_targetInfo.getLinkerOptions()._noInhibitExec ||
- _targetInfo.getLinkerOptions()._outputKind == OutputKind::Relocatable)) {
+ if (!undefinedAtoms.empty()) {
// FIXME: need diagonstics interface for writing error messages
- bool isError = false;
+ bool foundUndefines = false;
for (const UndefinedAtom *undefAtom : undefinedAtoms) {
if (undefAtom->canBeNull() == UndefinedAtom::canBeNullNever) {
- llvm::errs() << "Undefined Symbol: " << undefAtom->file().path()
- << " : " << undefAtom->name() << "\n";
- isError = true;
+ foundUndefines = true;
+ if (_targetInfo.printRemainingUndefines()) {
+ llvm::errs() << "Undefined Symbol: " << undefAtom->file().path()
+ << " : " << undefAtom->name() << "\n";
+ }
}
}
- if (isError)
- llvm::report_fatal_error("symbol(s) not found");
+ if (foundUndefines) {
+ if (_targetInfo.printRemainingUndefines())
+ llvm::errs() << "symbol(s) not found\n";
+ return true;
+ }
}
+ return false;
}
@@ -357,16 +360,20 @@ void Resolver::linkTimeOptimize() {
// FIX ME
}
-void Resolver::resolve() {
+bool Resolver::resolve() {
this->buildInitialAtomList();
this->resolveUndefines();
this->updateReferences();
this->deadStripOptimize();
- this->checkUndefines(false);
+ if (this->checkUndefines(false)) {
+ if (!_targetInfo.allowRemainingUndefines())
+ return true;
+ }
this->removeCoalescedAwayAtoms();
this->checkDylibSymbolCollisions();
this->linkTimeOptimize();
this->_result.addAtoms(_atoms);
+ return false;
}
void Resolver::MergedFile::addAtom(const Atom& atom) {
diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp
index 36e52d8ed07..4ded5a62597 100644
--- a/lld/lib/Core/SymbolTable.cpp
+++ b/lld/lib/Core/SymbolTable.cpp
@@ -13,7 +13,6 @@
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/InputFiles.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/SharedLibraryAtom.h"
@@ -184,8 +183,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
useNew = false;
}
else {
- if (_targetInfo.getLinkerOptions().
- _warnIfCoalesableAtomsHaveDifferentCanBeNull) {
+ if (_targetInfo.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
// FIXME: need diagonstics interface for writing warning messages
llvm::errs() << "lld warning: undefined symbol "
<< existingUndef->name()
@@ -210,8 +208,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
bool sameName = curShLib->loadName().equals(newShLib->loadName());
if ( !sameName ) {
useNew = false;
- if (_targetInfo.getLinkerOptions().
- _warnIfCoalesableAtomsHaveDifferentLoadName) {
+ if (_targetInfo.warnIfCoalesableAtomsHaveDifferentLoadName()) {
// FIXME: need diagonstics interface for writing warning messages
llvm::errs() << "lld warning: shared library symbol "
<< curShLib->name()
@@ -223,8 +220,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
}
else if ( ! sameNullness ) {
useNew = false;
- if (_targetInfo.getLinkerOptions().
- _warnIfCoalesableAtomsHaveDifferentCanBeNull) {
+ if (_targetInfo.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
// FIXME: need diagonstics interface for writing warning messages
llvm::errs() << "lld warning: shared library symbol "
<< curShLib->name()
diff --git a/lld/lib/Core/TargetInfo.cpp b/lld/lib/Core/TargetInfo.cpp
index da834fb2c9c..05d7ffa5989 100644
--- a/lld/lib/Core/TargetInfo.cpp
+++ b/lld/lib/Core/TargetInfo.cpp
@@ -8,28 +8,49 @@
//===----------------------------------------------------------------------===//
#include "lld/Core/TargetInfo.h"
-
-#include "lld/Core/LinkerOptions.h"
+#include "lld/ReaderWriter/Writer.h"
#include "llvm/ADT/Triple.h"
namespace lld {
+
+TargetInfo::TargetInfo()
+ : Reader(*this)
+ , _deadStrip(false)
+ , _globalsAreDeadStripRoots(false)
+ , _searchArchivesToOverrideTentativeDefinitions(false)
+ , _searchSharedLibrariesToOverrideTentativeDefinitions(false)
+ , _warnIfCoalesableAtomsHaveDifferentCanBeNull(false)
+ , _warnIfCoalesableAtomsHaveDifferentLoadName(false)
+ , _forceLoadAllArchives(false)
+ , _printRemainingUndefines(true)
+ , _allowRemainingUndefines(false)
+{
+}
+
TargetInfo::~TargetInfo() {}
-llvm::Triple TargetInfo::getTriple() const {
- return llvm::Triple(llvm::Triple::normalize(_options._target));
+
+error_code TargetInfo::readFile(StringRef path,
+ std::vector<std::unique_ptr<File>> &result) const {
+ OwningPtr<llvm::MemoryBuffer> opmb;
+ if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb))
+ return ec;
+
+ std::unique_ptr<MemoryBuffer> mb(opmb.take());
+ return this->parseFile(mb, result);
}
-bool TargetInfo::is64Bits() const {
- return getTriple().isArch64Bit();
+error_code TargetInfo::writeFile(const File &linkedFile) const {
+ return this->writer().writeFile(linkedFile, _outputPath);
}
-bool TargetInfo::isLittleEndian() const {
- // TODO: Do this properly. It is not defined purely by arch.
- return true;
+void TargetInfo::addImplicitFiles(InputFiles& inputs) const {
+ this->writer().addFiles(inputs);
}
-StringRef TargetInfo::getEntry() const {
- return _options._entrySymbol;
+void TargetInfo::addPasses(PassManager &pm) const {
}
+
+
} // end namespace lld
diff --git a/lld/lib/Driver/CMakeLists.txt b/lld/lib/Driver/CMakeLists.txt
index 13e6298b9a2..30aa26aa9f1 100644
--- a/lld/lib/Driver/CMakeLists.txt
+++ b/lld/lib/Driver/CMakeLists.txt
@@ -2,12 +2,16 @@ set(LLVM_TARGET_DEFINITIONS LDOptions.td)
tablegen(LLVM LDOptions.inc -gen-opt-parser-defs)
set(LLVM_TARGET_DEFINITIONS CoreOptions.td)
tablegen(LLVM CoreOptions.inc -gen-opt-parser-defs)
+set(LLVM_TARGET_DEFINITIONS DarwinOptions.td)
+tablegen(LLVM DarwinOptions.inc -gen-opt-parser-defs)
add_public_tablegen_target(DriverOptionsTableGen)
add_lld_library(lldDriver
+ CoreDriver.cpp
+ DarwinLdDriver.cpp
Driver.cpp
- Drivers.cpp
- LinkerInvocation.cpp
+ GnuLdDriver.cpp
+ UniversalDriver.cpp
)
add_dependencies(lldDriver DriverOptionsTableGen)
diff --git a/lld/lib/Driver/CoreDriver.cpp b/lld/lib/Driver/CoreDriver.cpp
new file mode 100644
index 00000000000..a4fb2166a4b
--- /dev/null
+++ b/lld/lib/Driver/CoreDriver.cpp
@@ -0,0 +1,158 @@
+//===- lib/Driver/CoreDriver.cpp ------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Driver/Driver.h"
+#include "lld/ReaderWriter/CoreTargetInfo.h"
+#include "lld/ReaderWriter/Reader.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+
+using namespace lld;
+
+namespace {
+
+// Create enum with OPT_xxx values for each option in DarwinOptions.td
+enum CoreOpt {
+ OPT_INVALID = 0,
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
+ OPT_##ID,
+#include "CoreOptions.inc"
+ LastOption
+#undef OPTION
+};
+
+// Create prefix string literals used in CoreOptions.td
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "CoreOptions.inc"
+#undef PREFIX
+
+// Create table mapping all options defined in CoreOptions.td
+static const llvm::opt::OptTable::Info infoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
+ PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
+#include "CoreOptions.inc"
+#undef OPTION
+};
+
+// Create OptTable class for parsing actual command line arguments
+class CoreOptTable : public llvm::opt::OptTable {
+public:
+ CoreOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
+};
+
+
+
+} // namespace anonymous
+
+
+namespace lld {
+
+bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
+ CoreTargetInfo info;
+ if (parse(argc, argv, info))
+ return true;
+
+ return Driver::link(info);
+}
+
+
+bool CoreDriver::parse(int argc, const char *argv[],
+ CoreTargetInfo &info, raw_ostream &diagnostics) {
+ // Parse command line options using CoreOptions.td
+ std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
+ CoreOptTable table;
+ unsigned missingIndex;
+ unsigned missingCount;
+ parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc],
+ missingIndex, missingCount));
+ if (missingCount) {
+ diagnostics << "error: missing arg value for '"
+ << parsedArgs->getArgString(missingIndex)
+ << "' expected " << missingCount << " argument(s).\n";
+ 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 -e xxx
+ if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry))
+ info.setEntrySymbolName(entry->getValue());
+
+ // Handle -o xxx
+ if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_output))
+ info.setOutputPath(outpath->getValue());
+ else
+ info.setOutputPath("-");
+
+ // Handle --dead_strip
+ if (parsedArgs->getLastArg(OPT_dead_strip))
+ info.setDeadStripping(true);
+ else
+ info.setDeadStripping(false);
+
+ // Handle --keep-globals
+ if (parsedArgs->getLastArg(OPT_keep_globals))
+ info.setGlobalsAreDeadStripRoots(true);
+ else
+ info.setGlobalsAreDeadStripRoots(false);
+
+ // Handle --undefines-are-errors
+ if (parsedArgs->getLastArg(OPT_undefines_are_errors)) {
+ info.setPrintRemainingUndefines(true);
+ info.setAllowRemainingUndefines(false);
+ }
+ else {
+ info.setPrintRemainingUndefines(false);
+ info.setAllowRemainingUndefines(true);
+ }
+
+ // Handle --commons-search-archives
+ if (parsedArgs->getLastArg(OPT_commons_search_archives))
+ info.setSearchArchivesToOverrideTentativeDefinitions(true);
+ else
+ info.setSearchArchivesToOverrideTentativeDefinitions(false);
+
+ // Handle --add-pass xxx option
+ for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_add_pass),
+ ie = parsedArgs->filtered_end();
+ it != ie; ++it) {
+ info.addPassNamed((*it)->getValue());
+ }
+
+ // Handle input files
+ for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT),
+ ie = parsedArgs->filtered_end();
+ it != ie; ++it) {
+ info.appendInputFile((*it)->getValue());
+ }
+
+ return false;
+}
+
+} // namespace lld
+
diff --git a/lld/lib/Driver/CoreOptions.td b/lld/lib/Driver/CoreOptions.td
index 8a53fd35cbe..df7cb41737d 100644
--- a/lld/lib/Driver/CoreOptions.td
+++ b/lld/lib/Driver/CoreOptions.td
@@ -1,22 +1,15 @@
include "llvm/Option/OptParser.td"
-def core : Flag<["-"], "core">;
-def flavor : Separate<["-"], "flavor">;
-def target : Separate<["-"], "target">, HelpText<"Target triple to link for">;
-def mllvm : Separate<["-"], "mllvm">, HelpText<"Options to pass to LLVM">;
-
-def output : Joined<["-"], "output=">;
-def entry : Joined<["-"], "entry=">;
-def input_search_path : Joined<["-"], "input-search-path=">;
-def output_type : Joined<["-"], "output-type=">;
-def relocatable : Flag<["-"], "relocatable">;
+def output : Separate<["-"], "o">;
+def entry : Separate<["-"], "e">;
-def OCTOTHORPE_OCTOTHORPE_OCTOTHORPE : Flag<["-"], "###">;
+def dead_strip : Flag<["--"], "dead-strip">;
+def undefines_are_errors : Flag<["--"], "undefines-are-errors">;
+def keep_globals : Flag<["--"], "keep-globals">;
+def commons_search_archives : Flag<["--"], "commons-search-archives">;
-def emit_yaml : Flag<["-"], "emit-yaml">;
+def add_pass : Separate<["--"], "add-pass">;
-def noinhibit_exec : Flag<["-"], "noinhibit-exec">,
- HelpText<"Retain the executable output file whenever it is still usable">;
+def target : Separate<["-"], "target">, HelpText<"Target triple to link for">;
+def mllvm : Separate<["-"], "mllvm">, HelpText<"Options to pass to LLVM">;
-def merge_strings : Flag<["-"], "merge-strings">,
- HelpText<"Merge common strings across mergeable sections">;
diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp
new file mode 100644
index 00000000000..1dbe5dfec0d
--- /dev/null
+++ b/lld/lib/Driver/DarwinLdDriver.cpp
@@ -0,0 +1,197 @@
+//===- lib/Driver/DarwinLdDriver.cpp --------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Concrete instance of the Driver for darwin's ld.
+///
+//===----------------------------------------------------------------------===//
+
+#include "lld/Driver/Driver.h"
+#include "lld/ReaderWriter/MachOTargetInfo.h"
+#include "../ReaderWriter/MachO/MachOFormat.hpp"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+
+
+namespace {
+
+// Create enum with OPT_xxx values for each option in DarwinOptions.td
+enum DarwinOpt {
+ OPT_INVALID = 0,
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
+ OPT_##ID,
+#include "DarwinOptions.inc"
+ LastOption
+#undef OPTION
+};
+
+// Create prefix string literals used in DarwinOptions.td
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "DarwinOptions.inc"
+#undef PREFIX
+
+// Create table mapping all options defined in DarwinOptions.td
+static const llvm::opt::OptTable::Info infoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
+ PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
+#include "DarwinOptions.inc"
+#undef OPTION
+};
+
+// Create OptTable class for parsing actual command line arguments
+class DarwinLdOptTable : public llvm::opt::OptTable {
+public:
+ DarwinLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
+};
+
+
+} // namespace anonymous
+
+namespace lld {
+
+bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
+ raw_ostream &diagnostics) {
+ MachOTargetInfo info;
+ if (parse(argc, argv, info, diagnostics))
+ return true;
+
+ return link(info, diagnostics);
+}
+
+
+
+bool DarwinLdDriver::parse(int argc, const char *argv[],
+ MachOTargetInfo &info, raw_ostream &diagnostics) {
+ // Parse command line options using DarwinOptions.td
+ std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
+ DarwinLdOptTable table;
+ unsigned missingIndex;
+ unsigned missingCount;
+ parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc],
+ missingIndex, missingCount));
+ if (missingCount) {
+ diagnostics << "error: missing arg value for '"
+ << parsedArgs->getArgString(missingIndex)
+ << "' expected " << missingCount << " argument(s).\n";
+ 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";
+ }
+
+ // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )
+ if ( llvm::opt::Arg *kind = parsedArgs->getLastArg(OPT_dylib, OPT_relocatable,
+ OPT_bundle, OPT_static, OPT_preload)) {
+ switch (kind->getOption().getID()) {
+ case OPT_dylib:
+ info.setOutputFileType(mach_o::MH_DYLIB);
+ break;
+ case OPT_relocatable:
+ info.setPrintRemainingUndefines(false);
+ info.setAllowRemainingUndefines(true);
+ info.setOutputFileType(mach_o::MH_OBJECT);
+ break;
+ case OPT_bundle:
+ info.setOutputFileType(mach_o::MH_BUNDLE);
+ break;
+ case OPT_static:
+ info.setOutputFileType(mach_o::MH_EXECUTE);
+ break;
+ case OPT_preload:
+ info.setOutputFileType(mach_o::MH_PRELOAD);
+ break;
+ }
+ }
+
+ // Handle -e xxx
+ if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry))
+ info.setEntrySymbolName(entry->getValue());
+
+ // Handle -o xxx
+ if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_output))
+ info.setOutputPath(outpath->getValue());
+
+ // Handle -dead_strip
+ if (parsedArgs->getLastArg(OPT_dead_strip))
+ info.setDeadStripping(true);
+
+ // Handle -arch xxx
+ if (llvm::opt::Arg *archStr = parsedArgs->getLastArg(OPT_arch)) {
+ info.setArch(llvm::StringSwitch<MachOTargetInfo::Arch>(archStr->getValue())
+ .Case("x86_64", MachOTargetInfo::arch_x86_64)
+ .Case("i386", MachOTargetInfo::arch_x86)
+ .Case("armv6", MachOTargetInfo::arch_armv6)
+ .Case("armv7", MachOTargetInfo::arch_armv7)
+ .Case("armv7s", MachOTargetInfo::arch_armv7s)
+ .Default(MachOTargetInfo::arch_unknown));
+ }
+
+ // Handle -macosx_version_min or -ios_version_min
+ if (llvm::opt::Arg *minOS = parsedArgs->getLastArg(
+ OPT_macosx_version_min,
+ OPT_ios_version_min,
+ OPT_ios_simulator_version_min)) {
+ switch (minOS->getOption().getID()) {
+ case OPT_macosx_version_min:
+ if (info.setOS(MachOTargetInfo::OS::macOSX, minOS->getValue())) {
+ diagnostics << "error: malformed macosx_version_min value\n";
+ return true;
+ }
+ break;
+ case OPT_ios_version_min:
+ if (info.setOS(MachOTargetInfo::OS::iOS, minOS->getValue())) {
+ diagnostics << "error: malformed ios_version_min value\n";
+ return true;
+ }
+ break;
+ case OPT_ios_simulator_version_min:
+ if (info.setOS(MachOTargetInfo::OS::iOS_simulator, minOS->getValue())) {
+ diagnostics << "error: malformed ios_simulator_version_min value\n";
+ return true;
+ }
+ break;
+ }
+ }
+ else {
+ // No min-os version on command line, check environment variables
+
+ }
+
+ // Handle input files
+ for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT),
+ ie = parsedArgs->filtered_end();
+ it != ie; ++it) {
+ info.appendInputFile((*it)->getValue());
+ }
+
+ return false;
+}
+
+
+} // namespace lld
+
+
diff --git a/lld/lib/Driver/DarwinOptions.td b/lld/lib/Driver/DarwinOptions.td
new file mode 100644
index 00000000000..b51d97d5602
--- /dev/null
+++ b/lld/lib/Driver/DarwinOptions.td
@@ -0,0 +1,30 @@
+include "llvm/Option/OptParser.td"
+
+// output kinds
+def relocatable : Flag<["-"], "r">, HelpText<"create relocatable output">;
+def static : Flag<["-"], "static">;
+def dynamic : Flag<["-"], "dynamic">;
+def dylib : Flag<["-"], "dylib">;
+def bundle : Flag<["-"], "bundle">;
+def execute : Flag<["-"], "execute">;
+def preload : Flag<["-"], "preload">;
+
+// linking options
+def dead_strip : Flag<["-"], "dead_strip">;
+def entry : Separate<["-"], "e">, HelpText<"entry symbol name">;
+def mllvm : Separate<["-"], "mllvm">, HelpText<"Options to pass to LLVM">;
+def arch : Separate<["-"], "arch">, HelpText<"architecture">;
+def macosx_version_min : Separate<["-"], "macosx_version_min">,
+ HelpText<"min Mac OS X version">;
+def ios_version_min : Separate<["-"], "ios_version_min">,
+ HelpText<"min iOS version">;
+def ios_simulator_version_min : Separate<["-"], "ios_simulator_version_min">,
+ HelpText<"min iOS simulator version">;
+
+// search options
+def L : Joined<["-"], "L">;
+
+// inputs and outputs
+def output : Separate<["-"], "o">, HelpText<"output file name">;
+
+
diff --git a/lld/lib/Driver/Driver.cpp b/lld/lib/Driver/Driver.cpp
index 5f7f4e6f555..cb3c611c2ce 100644
--- a/lld/lib/Driver/Driver.cpp
+++ b/lld/lib/Driver/Driver.cpp
@@ -8,7 +8,81 @@
//===----------------------------------------------------------------------===//
#include "lld/Driver/Driver.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/InputFiles.h"
+#include "lld/Core/Resolver.h"
+#include "lld/Core/PassManager.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/Writer.h"
-using namespace lld;
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace lld {
+
+/// This is where the link is actually performed.
+bool Driver::link(const TargetInfo &targetInfo, raw_ostream &diagnostics) {
+ // Honor -mllvm
+ if (!targetInfo.llvmOptions().empty()) {
+ unsigned numArgs = targetInfo.llvmOptions().size();
+ const char **args = new const char*[numArgs + 2];
+ args[0] = "lld (LLVM option parsing)";
+ for (unsigned i = 0; i != numArgs; ++i)
+ args[i + 1] = targetInfo.llvmOptions()[i];
+ args[numArgs + 1] = 0;
+ llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
+ }
+
+ // Read inputs
+ InputFiles inputs;
+ for (const auto &input : targetInfo.inputFiles()) {
+ std::vector<std::unique_ptr<File>> files;
+ if (targetInfo.logInputFiles())
+ llvm::outs() << input.getPath() << "\n";
+
+ error_code ec = targetInfo.readFile(input.getPath(), files);
+ if (ec) {
+ diagnostics << "Failed to read file: " << input.getPath() << ": "
+ << ec.message() << "\n";
+ return true;
+ }
+ inputs.appendFiles(files);
+ }
+
+ // Give target a chance to add files.
+ targetInfo.addImplicitFiles(inputs);
+
+ // assign an ordinal to each file so sort() can preserve command line order
+ inputs.assignFileOrdinals();
+
+ // Do core linking.
+ Resolver resolver(targetInfo, inputs);
+ if (resolver.resolve()) {
+ if (!targetInfo.allowRemainingUndefines())
+ return true;
+ }
+ MutableFile &merged = resolver.resultFile();
+
+ // Run passes on linked atoms.
+ PassManager pm;
+ targetInfo.addPasses(pm);
+ pm.runOnFile(merged);
+
+ // Give linked atoms to Writer to generate output file.
+ if (error_code ec = targetInfo.writeFile(merged)) {
+ diagnostics << "Failed to write file '" << targetInfo.outputPath()
+ << "': " << ec.message() << "\n";
+ return true;
+ }
+
+ return false;
+}
+
+
+} // namespace
-Driver::~Driver() {}
diff --git a/lld/lib/Driver/Drivers.cpp b/lld/lib/Driver/Drivers.cpp
deleted file mode 100644
index d2c1b732046..00000000000
--- a/lld/lib/Driver/Drivers.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-//===- lib/Driver/Drivers.cpp - Linker Driver Emulators -------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Concrete instances of the Driver interface.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Driver/Driver.h"
-
-#include "lld/Core/LinkerOptions.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lld;
-
-namespace core {
-enum ID {
- OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
- OPT_##ID,
-#include "CoreOptions.inc"
- LastOption
-#undef OPTION
-};
-
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "CoreOptions.inc"
-#undef PREFIX
-
-static const llvm::opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
- { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
- PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
-#include "CoreOptions.inc"
-#undef OPTION
-};
-
-class CoreOptTable : public llvm::opt::OptTable {
-public:
- CoreOptTable() : OptTable(InfoTable, llvm::array_lengthof(InfoTable)){}
-};
-}
-
-namespace ld {
-enum LDOpt {
- OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
- OPT_##ID,
-#include "LDOptions.inc"
- LastOption
-#undef OPTION
-};
-
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "LDOptions.inc"
-#undef PREFIX
-
-static const llvm::opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
- { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
- PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
-#include "LDOptions.inc"
-#undef OPTION
-};
-
-class LDOptTable : public llvm::opt::OptTable {
-public:
- LDOptTable() : OptTable(InfoTable, llvm::array_lengthof(InfoTable)){}
-};
-}
-
-class LDDriver LLVM_FINAL : public Driver {
-public:
- LDDriver(StringRef defaultTargetTriple) : Driver(defaultTargetTriple) {}
-
- virtual std::unique_ptr<llvm::opt::DerivedArgList>
- transform(llvm::ArrayRef<const char *> args) {
- assert(!_inputArgs && "transform may only be called once!");
-
- unsigned missingIndex, missingCount;
- _inputArgs.reset(_opt.ParseArgs( args.begin(), args.end()
- , missingIndex, missingCount));
-
- if (missingCount) {
- llvm::errs() << "error: missing arg value for '"
- << _inputArgs->getArgString(missingIndex)
- << "' expected " << missingCount << " argument(s).\n";
- return std::unique_ptr<llvm::opt::DerivedArgList>();
- }
-
- for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_UNKNOWN),
- ie = _inputArgs->filtered_end();
- it != ie; ++it) {
- llvm::errs() << "warning: ignoring unknown argument: "
- << (*it)->getAsString(*_inputArgs) << "\n";
- }
-
- std::unique_ptr<llvm::opt::DerivedArgList> newArgs(
- new llvm::opt::DerivedArgList(*_inputArgs));
-
- bool isOutputDynamic = false;
-
- if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_target)) {
- newArgs->AddSeparateArg( A, _core.getOption(core::OPT_target)
- , A->getValue());
- } else {
- assert(!_defaultTargetTriple.empty() && "Got empty target triple!");
- newArgs->AddSeparateArg(nullptr, _core.getOption(core::OPT_target)
- , _defaultTargetTriple);
- }
-
- if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_entry))
- newArgs->AddJoinedArg(A, _core.getOption(core::OPT_entry), A->getValue());
-
- if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_output))
- newArgs->AddJoinedArg(A, _core.getOption(core::OPT_output),
- A->getValue());
- else
- newArgs->AddJoinedArg(nullptr, _core.getOption(core::OPT_output),
- "a.out");
-
- if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_static))
- newArgs->AddJoinedArg(A, _core.getOption(core::OPT_output_type),
- newArgs->MakeArgString("static"));
- else {
- newArgs->AddJoinedArg(nullptr, _core.getOption(core::OPT_output_type),
- newArgs->MakeArgString("dynamic"));
- isOutputDynamic = true;
- }
-
- if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_relocatable))
- newArgs->AddFlagArg(A, _core.getOption(core::OPT_relocatable));
-
- if (llvm::opt::Arg *A =
- _inputArgs->getLastArg(ld::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE))
- newArgs->AddFlagArg(A, _core.getOption(
- core::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE));
-
- if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_emit_yaml))
- newArgs->AddFlagArg(A, _core.getOption(core::OPT_emit_yaml));
-
- if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_noinhibit_exec))
- newArgs->AddFlagArg(A, _core.getOption(core::OPT_noinhibit_exec));
-
- if (llvm::opt::Arg *A = _inputArgs->getLastArg(ld::OPT_merge_strings))
- newArgs->AddFlagArg(A, _core.getOption(core::OPT_merge_strings));
-
- // Copy search paths.
- for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_L),
- ie = _inputArgs->filtered_end();
- it != ie; ++it) {
- newArgs->AddPositionalArg(
- *it, _core.getOption(core::OPT_input_search_path), (*it)->getValue());
- _inputSearchPaths.push_back((*it)->getValue());
- }
-
- // Copy input args.
- for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_INPUT,
- ld::OPT_l),
- ie = _inputArgs->filtered_end();
- it != ie; ++it) {
- StringRef inputPath;
- if ((*it)->getOption().getID() == ld::OPT_l) {
- StringRef libName = (*it)->getValue();
- SmallString<128> p;
- for (const auto &path : _inputSearchPaths) {
- if (isOutputDynamic) {
- p = path;
- llvm::sys::path::append(p, Twine("lib") + libName + ".so");
- if (llvm::sys::fs::exists(p.str())) {
- inputPath = newArgs->MakeArgString(p);
- break;
- }
- }
- p = path;
- llvm::sys::path::append(p, Twine("lib") + libName + ".a");
- if (llvm::sys::fs::exists(p.str())) {
- inputPath = newArgs->MakeArgString(p);
- break;
- }
- }
- if (inputPath.empty())
- llvm_unreachable("Failed to lookup library!");
- } else
- inputPath = (*it)->getValue();
- newArgs->AddPositionalArg(*it, _core.getOption(core::OPT_INPUT),
- inputPath);
- }
-
- // Copy mllvm
- for (llvm::opt::arg_iterator it = _inputArgs->filtered_begin(ld::OPT_mllvm),
- ie = _inputArgs->filtered_end();
- it != ie; ++it) {
- newArgs->AddPositionalArg(*it, _core.getOption(core::OPT_mllvm),
- (*it)->getValue());
- }
-
- return std::move(newArgs);
- }
-
-private:
- std::unique_ptr<llvm::opt::InputArgList> _inputArgs;
- core::CoreOptTable _core;
- ld::LDOptTable _opt;
- // Local cache of search paths so we can do lookups on -l.
- std::vector<std::string> _inputSearchPaths;
-};
-
-std::unique_ptr<Driver> Driver::create( Driver::Flavor flavor
- , StringRef defaultTargetTriple) {
- switch (flavor) {
- case Flavor::ld:
- return std::unique_ptr<Driver>(new LDDriver(defaultTargetTriple));
- case Flavor::core:
- case Flavor::ld64:
- case Flavor::link:
- case Flavor::invalid:
- break;
- }
- llvm_unreachable("Unsupported flavor");
-}
-
-std::unique_ptr<llvm::opt::ArgList>
-lld::parseCoreArgs(llvm::ArrayRef<const char *> args) {
- core::CoreOptTable core;
- unsigned missingIndex, missingCount;
- std::unique_ptr<llvm::opt::ArgList> list(
- core.ParseArgs( args.begin(), args.end(), missingIndex, missingCount));
-
- if (missingCount) {
- llvm::errs() << "error: missing arg value for '"
- << list->getArgString(missingIndex)
- << "' expected " << missingCount << " argument(s).\n";
- return std::unique_ptr<llvm::opt::ArgList>();
- }
-
- bool hasUnknown = false;
- for (llvm::opt::arg_iterator it = list->filtered_begin(ld::OPT_UNKNOWN),
- ie = list->filtered_end();
- it != ie; ++it) {
- llvm::errs() << "error: ignoring unknown argument: "
- << (*it)->getAsString(*list) << "\n";
- hasUnknown = true;
- }
- if (hasUnknown)
- return std::unique_ptr<llvm::opt::ArgList>();
-
- return list;
-}
-
-LinkerOptions lld::generateOptions(const llvm::opt::ArgList &args) {
- LinkerOptions ret;
-
- for (llvm::opt::arg_iterator it = args.filtered_begin(ld::OPT_INPUT),
- ie = args.filtered_end();
- it != ie; ++it) {
- ret._input.push_back(LinkerInput((*it)->getValue()));
- }
-
- StringRef outputType = args.getLastArgValue(core::OPT_output_type);
- ret._outputKind = llvm::StringSwitch<OutputKind>(outputType)
- .Case("static", OutputKind::StaticExecutable)
- .Case("dynamic", OutputKind::DynamicExecutable)
- .Case("relocatable", OutputKind::Relocatable)
- .Case("shared", OutputKind::Shared)
- .Case("stubs", OutputKind::SharedStubs)
- .Case("core", OutputKind::Core)
- .Case("debug-symbols", OutputKind::DebugSymbols)
- .Case("bundle", OutputKind::Bundle)
- .Case("preload", OutputKind::Preload)
- .Default(OutputKind::Invalid);
-
- ret._inputSearchPaths = args.getAllArgValues(core::OPT_input_search_path);
- ret._llvmArgs = args.getAllArgValues(core::OPT_mllvm);
- ret._target = llvm::Triple::normalize(args.getLastArgValue(core::OPT_target));
- ret._outputPath = args.getLastArgValue(core::OPT_output);
- ret._entrySymbol = args.getLastArgValue(core::OPT_entry);
- if (args.hasArg(core::OPT_relocatable))
- ret._outputKind = OutputKind::Relocatable;
- ret._outputCommands = args.hasArg(core::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE);
- ret._outputYAML = args.hasArg(core::OPT_emit_yaml);
- ret._noInhibitExec = args.hasArg(core::OPT_noinhibit_exec);
- ret._mergeCommonStrings = args.hasArg(core::OPT_merge_strings);
-
- return std::move(ret);
-}
diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp
new file mode 100644
index 00000000000..55e38580029
--- /dev/null
+++ b/lld/lib/Driver/GnuLdDriver.cpp
@@ -0,0 +1,241 @@
+//===- lib/Driver/GnuLdDriver.cpp -----------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Concrete instance of the Driver for GNU's ld.
+///
+//===----------------------------------------------------------------------===//
+
+#include "lld/Driver/Driver.h"
+#include "lld/ReaderWriter/ELFTargetInfo.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+
+using namespace lld;
+
+
+namespace {
+
+// Create enum with OPT_xxx values for each option in LDOptions.td
+enum LDOpt {
+ OPT_INVALID = 0,
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
+ OPT_##ID,
+#include "LDOptions.inc"
+ LastOption
+#undef OPTION
+};
+
+// Create prefix string literals used in LDOptions.td
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "LDOptions.inc"
+#undef PREFIX
+
+// Create table mapping all options defined in LDOptions.td
+static const llvm::opt::OptTable::Info infoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
+ PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
+#include "LDOptions.inc"
+#undef OPTION
+};
+
+
+// Create OptTable class for parsing actual command line arguments
+class GnuLdOptTable : public llvm::opt::OptTable {
+public:
+ GnuLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
+};
+
+} // namespace
+
+
+
+bool GnuLdDriver::linkELF(int argc, const char *argv[],
+ raw_ostream &diagnostics) {
+ std::unique_ptr<ELFTargetInfo> options(parse(argc, argv, diagnostics));
+ if (!options)
+ return true;
+
+ return link(*options, diagnostics);
+}
+
+
+std::unique_ptr<ELFTargetInfo> GnuLdDriver::parse(int argc, const char *argv[],
+ raw_ostream &diagnostics) {
+ // Parse command line options using LDOptions.td
+ std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
+ GnuLdOptTable table;
+ unsigned missingIndex;
+ unsigned missingCount;
+ parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc],
+ missingIndex, missingCount));
+ if (missingCount) {
+ diagnostics << "error: missing arg value for '"
+ << parsedArgs->getArgString(missingIndex)
+ << "' expected " << missingCount << " argument(s).\n";
+ return nullptr;
+ }
+
+ 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);
+ return nullptr;
+ }
+
+ // Use -target or use default target triple to instantiate TargetInfo
+ llvm::Triple triple;
+ if (llvm::opt::Arg *trip = parsedArgs->getLastArg(OPT_target))
+ triple = llvm::Triple(trip->getValue());
+ else
+ triple = getDefaultTarget(argv[0]);
+ std::unique_ptr<ELFTargetInfo> options(ELFTargetInfo::create(triple));
+
+ if (!options) {
+ diagnostics << "unknown target triple\n";
+ return nullptr;
+ }
+
+ // 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()) {
+ case OPT_relocatable:
+ options->setOutputFileType(llvm::ELF::ET_REL);
+ options->setPrintRemainingUndefines(false);
+ options->setAllowRemainingUndefines(true);
+ break;
+ case OPT_shared:
+ options->setOutputFileType(llvm::ELF::ET_DYN);
+ break;
+ case OPT_static:
+ options->setOutputFileType(llvm::ELF::ET_EXEC);
+ options->setIsStaticExecutable(true);
+ break;
+ }
+ }
+ else {
+ options->setOutputFileType(llvm::ELF::ET_EXEC);
+ options->setIsStaticExecutable(false);
+ }
+
+ // Handle --noinhibit-exec
+ if (parsedArgs->getLastArg(OPT_noinhibit_exec))
+ options->setAllowRemainingUndefines(true);
+
+ // Handle --force-load
+ if (parsedArgs->getLastArg(OPT_force_load))
+ options->setForceLoadAllArchives(true);
+
+ // Handle --merge-strings
+ if (parsedArgs->getLastArg(OPT_merge_strings))
+ options->setMergeCommonStrings(true);
+
+ // Handle -t
+ if (parsedArgs->getLastArg(OPT_t))
+ options->setLogInputFiles(true);
+
+ // Handle -Lxxx
+ for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_L),
+ ie = parsedArgs->filtered_end();
+ it != ie; ++it) {
+ options->appendSearchPath((*it)->getValue());
+ }
+
+ // Copy mllvm
+ for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm),
+ ie = parsedArgs->filtered_end();
+ it != ie; ++it) {
+ options->appendLLVMOption((*it)->getValue());
+ }
+
+ // 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());
+ break;
+ case OPT_l:
+ if (options->appendLibrary((*it)->getValue())) {
+ diagnostics << "Failed to find library for "
+ << (*it)->getValue() << "\n";
+ return nullptr;
+ }
+ break;
+ default:
+ llvm_unreachable("input option type not handled");
+ }
+ }
+
+ // Validate the combination of options used.
+ if (options->validate(diagnostics))
+ return nullptr;
+
+ return options;
+}
+
+
+/// Get the default target triple based on either the program name
+/// (e.g. "x86-ibm-linux-lld") or the primary target llvm was configured for.
+llvm::Triple GnuLdDriver::getDefaultTarget(const char *progName) {
+ SmallVector<StringRef, 4> components;
+ llvm::SplitString(llvm::sys::path::stem(progName), components, "-");
+ // If has enough parts to be start with a triple.
+ if (components.size() >= 4) {
+ llvm::Triple triple(components[0], components[1], components[2],
+ components[3]);
+ // If first component looks like an arch.
+ if (triple.getArch() != llvm::Triple::UnknownArch)
+ return triple;
+ }
+
+ // Fallback to use whatever default triple llvm was configured for.
+ return llvm::Triple(llvm::sys::getDefaultTargetTriple());
+}
+
diff --git a/lld/lib/Driver/LDOptions.td b/lld/lib/Driver/LDOptions.td
index 516d487b41a..47e8a3cf78a 100644
--- a/lld/lib/Driver/LDOptions.td
+++ b/lld/lib/Driver/LDOptions.td
@@ -1,27 +1,29 @@
include "llvm/Option/OptParser.td"
-def flavor : Separate<["-"], "flavor">;
-def target : Separate<["-"], "target">, HelpText<"Target triple to link for">;
+def target : Separate<["-"], "target">,
+ MetaVarName<"<triple>">,
+ HelpText<"Target triple to link for">;
+
def mllvm : Separate<["-"], "mllvm">, HelpText<"Options to pass to LLVM">;
-def entry : Joined<["--"], "entry=">;
+def entry : Joined<["--"], "entry=">,
+ HelpText<"Name of entry point symbol">;
def entry_e : Separate<["-"], "e">, Alias<entry>;
-def output : Joined<["--"], "output=">;
-def output_e : Separate<["-"], "o">, Alias<output>;
-
+def output : Separate<["-"], "o">,
+ MetaVarName<"<path>">,
+ HelpText<"Path to file to write output">;
+
def relocatable : Flag<["--"], "relocatable">;
def relocatable_r : Flag<["-"], "r">, Alias<relocatable>;
def dynamic_linker : Separate<["-"], "dynamic-linker">;
-def OCTOTHORPE_OCTOTHORPE_OCTOTHORPE : Flag<["-"], "###">;
-
-def emit_yaml : Flag<["-"], "emit-yaml">;
def m : Separate<["-"], "m">;
def z : Separate<["-"], "z">;
+def t : Flag<["-"], "t">;
def rpath : Separate<["-"], "rpath">;
def soname : Separate<["-"], "soname">;
@@ -32,12 +34,25 @@ def end_group : Flag<["--"], "end-group">;
def build_id : Flag<["--"], "build-id">;
def eh_frame_hdr : Flag<["--"], "eh-frame-hdr">;
-def L : Joined<["-"], "L">;
-def l : Joined<["-"], "l">;
+def help : Flag<["--"], "help">;
+
+def L : Joined<["-"], "L">,
+ MetaVarName<"<dir>">,
+ HelpText<"Directory to search for libraries">;
+def l : Joined<["-"], "l">,
+ MetaVarName<"<libName>">,
+ HelpText<"Root name of library to use">;
def hash_style : Joined <["--"], "hash-style=">;
def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
HelpText<"Retain the executable output file whenever it is still usable">;
-def merge_strings : Flag<["-"], "merge-strings">,
+def merge_strings : Flag<["--"], "merge-strings">,
HelpText<"Merge common strings across mergeable sections">;
+
+
+// extensions
+def emit_yaml : Flag<["-"], "emit-yaml">,
+ HelpText<"Write YAML instead of ELF">;
+def force_load : Flag<["--"], "force-load">,
+ HelpText<"Force load of all members in all static libraries">;
diff --git a/lld/lib/Driver/LinkerInvocation.cpp b/lld/lib/Driver/LinkerInvocation.cpp
deleted file mode 100644
index 21662774bd9..00000000000
--- a/lld/lib/Driver/LinkerInvocation.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//===- lib/Driver/LinkerInvocation.cpp - Linker Invocation ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Driver/LinkerInvocation.h"
-
-#include "lld/Core/InputFiles.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Resolver.h"
-#include "lld/ReaderWriter/ELFTargetInfo.h"
-#include "lld/ReaderWriter/Reader.h"
-#include "lld/ReaderWriter/Writer.h"
-
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lld;
-
-namespace {
-std::unique_ptr<TargetInfo> createTargetInfo(const LinkerOptions &lo) {
- return ELFTargetInfo::create(lo);
-}
-}
-
-void LinkerInvocation::operator()() {
- // Honor -mllvm
- if (!_options._llvmArgs.empty()) {
- unsigned NumArgs = _options._llvmArgs.size();
- const char **Args = new const char*[NumArgs + 2];
- Args[0] = "lld (LLVM option parsing)";
- for (unsigned i = 0; i != NumArgs; ++i)
- Args[i + 1] = _options._llvmArgs[i].c_str();
- Args[NumArgs + 1] = 0;
- llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
- }
-
- // Create target.
- std::unique_ptr<TargetInfo> targetInfo(createTargetInfo(_options));
-
- if (!targetInfo) {
- llvm::errs() << "Failed to create target for " << _options._target
- << "\n";
- return;
- }
-
- // Read inputs
- InputFiles inputs;
- for (const auto &input : _options._input) {
- auto reader = targetInfo->getReader(input);
- if (error_code ec = reader) {
- llvm::errs() << "Failed to get reader for: " << input.getPath() << ": "
- << ec.message() << "\n";
- return;
- }
-
- auto buffer = input.getBuffer();
- if (error_code ec = buffer) {
- llvm::errs() << "Failed to read file: " << input.getPath() << ": "
- << ec.message() << "\n";
- return;
- }
-
- std::vector<std::unique_ptr<File>> files;
- if (llvm::error_code ec = reader->parseFile(std::unique_ptr<MemoryBuffer>(MemoryBuffer::getMemBuffer(buffer->getBuffer(), buffer->getBufferIdentifier())), files)) {
- llvm::errs() << "Failed to read file: " << input.getPath() << ": "
- << ec.message() << "\n";
- return;
- }
- inputs.appendFiles(files);
- }
- inputs.assignFileOrdinals();
-
- auto writer = targetInfo->getWriter();
-
- // Give writer a chance to add files
- writer->addFiles(inputs);
-
- Resolver resolver(*targetInfo, inputs);
- resolver.resolve();
- MutableFile &merged = resolver.resultFile();
-
- PassManager pm;
- targetInfo->addPasses(pm);
- pm.runOnFile(merged);
-
- if (error_code ec = writer) {
- llvm::errs() << "Failed to get writer: " << ec.message() << ".\n";
- return;
- }
-
- if (error_code ec = writer->writeFile(merged, _options._outputPath))
- llvm::errs() << "Failed to write file: " << ec.message() << "\n";
-}
diff --git a/lld/lib/Driver/UniversalDriver.cpp b/lld/lib/Driver/UniversalDriver.cpp
new file mode 100644
index 00000000000..5164f9da69c
--- /dev/null
+++ b/lld/lib/Driver/UniversalDriver.cpp
@@ -0,0 +1,109 @@
+//===- lib/Driver/UniversalDriver.cpp -------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Concrete instance of the Driver for darwin's ld.
+///
+//===----------------------------------------------------------------------===//
+
+#include "lld/Driver/Driver.h"
+#include "lld/ReaderWriter/MachOTargetInfo.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+
+#include <memory>
+
+namespace lld {
+
+
+bool UniversalDriver::link(int argc, const char *argv[]) {
+ // Convert argv[] C-array to vector.
+ std::vector<const char *> args;
+ args.assign(&argv[0], &argv[argc]);
+
+ // Determine flavor of link based on command name or -flavor argument.
+ // Note: 'args' is modified to remove -flavor option.
+ Flavor flavor = selectFlavor(args);
+
+ // Switch to appropriate driver.
+ switch (flavor) {
+ case Flavor::gnu_ld:
+ return GnuLdDriver::linkELF(args.size(), &args[0]);
+ case Flavor::darwin_ld:
+ return DarwinLdDriver::linkMachO(args.size(), &args[0]);
+ case Flavor::core:
+ return CoreDriver::link(args.size(), &args[0]);
+ case Flavor::win_link:
+ llvm_unreachable("Unsupported flavor");
+ case Flavor::invalid:
+ return true;
+ }
+}
+
+
+
+
+
+/// Pick the flavor of driver to use based on the command line and
+/// host environment.
+UniversalDriver::Flavor UniversalDriver::selectFlavor(
+ std::vector<const char*> &args) {
+ // -core as first arg is shorthand for -flavor core.
+ if (args.size() >= 1 && StringRef(args[1]) == "-core") {
+ args.erase(args.begin() + 1);
+ return Flavor::core;
+ }
+ // Handle -flavor as first arg.
+ if (args.size() >= 2 && StringRef(args[1]) == "-flavor") {
+ Flavor flavor = strToFlavor(args[2]);
+ args.erase(args.begin() + 1);
+ args.erase(args.begin() + 1);
+ if (flavor == Flavor::invalid)
+ llvm::errs() << "error: '" << args[2] << "' invalid value for -flavor.\n";
+ return flavor;
+ }
+
+ // Check if flavor is at end of program name (e.g. "lld-gnu");
+ SmallVector<StringRef, 3> components;
+ llvm::SplitString(args[0], components, "-");
+ Flavor flavor = strToFlavor(components.back());
+
+ // If flavor still undetermined, then error out.
+ if (flavor == Flavor::invalid)
+ llvm::errs() << "error: failed to determine driver flavor from program name"
+ " '" << args[0] << "'.\n";
+ return flavor;
+}
+
+/// Maps flavor strings to Flavor enum values.
+UniversalDriver::Flavor UniversalDriver::strToFlavor(StringRef str) {
+ return llvm::StringSwitch<Flavor>(str)
+ .Case("gnu", Flavor::gnu_ld)
+ .Case("darwin", Flavor::darwin_ld)
+ .Case("link", Flavor::win_link)
+ .Case("core", Flavor::core)
+ .Case("ld", Flavor::gnu_ld) // deprecated
+ .Default(Flavor::invalid);
+}
+
+
+} // namespace lld
diff --git a/lld/lib/Passes/LayoutPass.cpp b/lld/lib/Passes/LayoutPass.cpp
index f6bf980006d..6edbcadbcbf 100644
--- a/lld/lib/Passes/LayoutPass.cpp
+++ b/lld/lib/Passes/LayoutPass.cpp
@@ -11,6 +11,7 @@
#define DEBUG_TYPE "LayoutPass"
#include "lld/Passes/LayoutPass.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Debug.h"
@@ -435,6 +436,29 @@ void LayoutPass::perform(MutableFile &mergedFile) {
// Build override maps
buildOrdinalOverrideMap(atomRange);
+ DEBUG_WITH_TYPE("layout", llvm::dbgs() << "unsorted atoms:\n");
+ for ( const DefinedAtom *atom : atomRange ) {
+ DEBUG_WITH_TYPE("layout", llvm::dbgs()
+ << " file=" << atom->file().path()
+ << ", name=" << atom->name()
+ << ", size=" << atom->size()
+ << ", type=" << atom->contentType()
+ << ", ordinal=" << atom->ordinal()
+ << "\n");
+ }
+
// sort the atoms
std::sort(atomRange.begin(), atomRange.end(), _compareAtoms);
+
+ DEBUG_WITH_TYPE("layout", llvm::dbgs() << "sorted atoms:\n");
+ for ( const DefinedAtom *atom : atomRange ) {
+ DEBUG_WITH_TYPE("layout", llvm::dbgs()
+ << " file=" << atom->file().path()
+ << ", name=" << atom->name()
+ << ", size=" << atom->size()
+ << ", type=" << atom->contentType()
+ << ", ordinal=" << atom->ordinal()
+ << "\n");
+ }
+
}
diff --git a/lld/lib/ReaderWriter/CMakeLists.txt b/lld/lib/ReaderWriter/CMakeLists.txt
index 2ad3165ece6..fa3e71e8a37 100644
--- a/lld/lib/ReaderWriter/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/CMakeLists.txt
@@ -6,6 +6,7 @@ add_subdirectory(Native)
add_subdirectory(PECOFF)
add_subdirectory(YAML)
add_lld_library(lldReaderWriter
+ CoreTargetInfo.cpp
LinkerScript.cpp
Reader.cpp
ReaderArchive.cpp
diff --git a/lld/lib/ReaderWriter/CoreTargetInfo.cpp b/lld/lib/ReaderWriter/CoreTargetInfo.cpp
new file mode 100644
index 00000000000..18da8378090
--- /dev/null
+++ b/lld/lib/ReaderWriter/CoreTargetInfo.cpp
@@ -0,0 +1,395 @@
+//===- lib/ReaderWriter/CoreTargetInfo.cpp --------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/CoreTargetInfo.h"
+
+#include "lld/Core/Pass.h"
+#include "lld/Core/PassManager.h"
+#include "lld/Passes/LayoutPass.h"
+
+#include "llvm/ADT/ArrayRef.h"
+
+
+using namespace lld;
+
+namespace {
+
+/// \brief Simple atom created by the stubs pass.
+class TestingStubAtom : public DefinedAtom {
+public:
+ TestingStubAtom(const File &F, const Atom&) : _file(F) {
+ static uint32_t lastOrdinal = 0;
+ _ordinal = lastOrdinal++;
+ }
+
+ virtual const File &file() const {
+ return _file;
+ }
+
+ virtual StringRef name() const {
+ return StringRef();
+ }
+
+ virtual uint64_t ordinal() const {
+ return _ordinal;
+ }
+
+ virtual uint64_t size() const {
+ return 0;
+ }
+
+ virtual Scope scope() const {
+ return DefinedAtom::scopeLinkageUnit;
+ }
+
+ virtual Interposable interposable() const {
+ return DefinedAtom::interposeNo;
+ }
+
+ virtual Merge merge() const {
+ return DefinedAtom::mergeNo;
+ }
+
+ virtual ContentType contentType() const {
+ return DefinedAtom::typeStub;
+ }
+
+ virtual Alignment alignment() const {
+ return Alignment(0, 0);
+ }
+
+ virtual SectionChoice sectionChoice() const {
+ return DefinedAtom::sectionBasedOnContent;
+ }
+
+ virtual StringRef customSectionName() const {
+ return StringRef();
+ }
+
+ virtual SectionPosition sectionPosition() const {
+ return sectionPositionAny;
+ }
+
+ virtual DeadStripKind deadStrip() const {
+ return DefinedAtom::deadStripNormal;
+ }
+
+ virtual ContentPermissions permissions() const {
+ return DefinedAtom::permR_X;
+ }
+
+ virtual bool isThumb() const {
+ return false;
+ }
+
+ virtual bool isAlias() const {
+ return false;
+ }
+
+ virtual ArrayRef<uint8_t> rawContent() const {
+ return ArrayRef<uint8_t>();
+ }
+
+ virtual reference_iterator begin() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual reference_iterator end() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual const Reference *derefIterator(const void *iter) const {
+ return nullptr;
+ }
+
+ virtual void incrementIterator(const void *&iter) const {
+ }
+
+private:
+ const File &_file;
+ uint32_t _ordinal;
+};
+
+/// \brief Simple atom created by the GOT pass.
+class TestingGOTAtom : public DefinedAtom {
+public:
+ TestingGOTAtom(const File &F, const Atom&) : _file(F) {
+ static uint32_t lastOrdinal = 0;
+ _ordinal = lastOrdinal++;
+ }
+
+ virtual const File &file() const {
+ return _file;
+ }
+
+ virtual StringRef name() const {
+ return StringRef();
+ }
+
+ virtual uint64_t ordinal() const {
+ return _ordinal;
+ }
+
+ virtual uint64_t size() const {
+ return 0;
+ }
+
+ virtual Scope scope() const {
+ return DefinedAtom::scopeLinkageUnit;
+ }
+
+ virtual Interposable interposable() const {
+ return DefinedAtom::interposeNo;
+ }
+
+ virtual Merge merge() const {
+ return DefinedAtom::mergeNo;
+ }
+
+ virtual ContentType contentType() const {
+ return DefinedAtom::typeGOT;
+ }
+
+ virtual Alignment alignment() const {
+ return Alignment(3, 0);
+ }
+
+ virtual SectionChoice sectionChoice() const {
+ return DefinedAtom::sectionBasedOnContent;
+ }
+
+ virtual StringRef customSectionName() const {
+ return StringRef();
+ }
+
+ virtual SectionPosition sectionPosition() const {
+ return sectionPositionAny;
+ }
+
+ virtual DeadStripKind deadStrip() const {
+ return DefinedAtom::deadStripNormal;
+ }
+
+ virtual ContentPermissions permissions() const {
+ return DefinedAtom::permRW_;
+ }
+
+ virtual bool isThumb() const {
+ return false;
+ }
+
+ virtual bool isAlias() const {
+ return false;
+ }
+
+ virtual ArrayRef<uint8_t> rawContent() const {
+ return ArrayRef<uint8_t>();
+ }
+
+ virtual reference_iterator begin() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual reference_iterator end() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual const Reference *derefIterator(const void *iter) const {
+ return nullptr;
+ }
+
+ virtual void incrementIterator(const void *&iter) const {
+ }
+
+private:
+ const File &_file;
+ uint32_t _ordinal;
+};
+
+class TestingPassFile : public MutableFile {
+public:
+ TestingPassFile(const TargetInfo &ti) : MutableFile(ti, "Testing pass") {}
+
+ virtual void addAtom(const Atom &atom) {
+ if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&atom))
+ _definedAtoms._atoms.push_back(defAtom);
+ else
+ llvm_unreachable("atom has unknown definition kind");
+ }
+
+ virtual DefinedAtomRange definedAtoms() {
+ return range<std::vector<const DefinedAtom*>::iterator>(
+ _definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
+ }
+
+ virtual const atom_collection<DefinedAtom> &defined() const {
+ return _definedAtoms;
+ }
+ virtual const atom_collection<UndefinedAtom> &undefined() const {
+ return _undefinedAtoms;
+ }
+ virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
+ return _sharedLibraryAtoms;
+ }
+ virtual const atom_collection<AbsoluteAtom> &absolute() const {
+ return _absoluteAtoms;
+ }
+
+private:
+ atom_collection_vector<DefinedAtom> _definedAtoms;
+ atom_collection_vector<UndefinedAtom> _undefinedAtoms;
+ atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+ atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+};
+
+struct TestingKindMapping {
+ const char *string;
+ int32_t value;
+ bool isBranch;
+ bool isGotLoad;
+ bool isGotUse;
+};
+
+//
+// Table of fixup kinds in YAML documents used for testing
+//
+const TestingKindMapping sKinds[] = {
+ {"in-group", -3, false, false, false},
+ {"layout-after", -2, false, false, false},
+ {"layout-before", -1, false, false, false},
+ {"call32", 2, true, false, false},
+ {"pcrel32", 3, false, false, false},
+ {"gotLoad32", 7, false, true, true},
+ {"gotUse32", 9, false, false, true},
+ {"lea32wasGot", 8, false, false, false},
+ {nullptr, 0, false, false, false}
+ };
+
+class TestingStubsPass : public StubsPass {
+public:
+ TestingStubsPass(const TargetInfo &ti) : _file(TestingPassFile(ti))
+ {}
+
+ virtual bool noTextRelocs() {
+ return true;
+ }
+
+ virtual bool isCallSite(int32_t kind) {
+ for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
+ if (kind == p->value)
+ return p->isBranch;
+ }
+ return false;
+ }
+
+ virtual const DefinedAtom *getStub(const Atom &target) {
+ const DefinedAtom *result = new TestingStubAtom(_file, target);
+ _file.addAtom(*result);
+ return result;
+ }
+
+ virtual void addStubAtoms(MutableFile &mergedFile) {
+ for (const DefinedAtom *stub : _file.defined() ) {
+ mergedFile.addAtom(*stub);
+ }
+ }
+
+private:
+ TestingPassFile _file;
+};
+
+class TestingGOTPass : public GOTPass {
+public:
+ TestingGOTPass(const TargetInfo &ti) : _file(TestingPassFile(ti))
+ {}
+
+ virtual bool noTextRelocs() {
+ return true;
+ }
+
+ virtual bool isGOTAccess(int32_t kind, bool &canBypassGOT) {
+ for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
+ if (kind == p->value) {
+ canBypassGOT = p->isGotLoad;
+ return p->isGotUse || p->isGotLoad;
+ }
+ }
+ return false;
+ }
+
+ virtual void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) {
+ if (targetIsNowGOT)
+ const_cast<Reference*>(ref)->setKind(3); // pcrel32
+ else
+ const_cast<Reference*>(ref)->setKind(8); // lea32wasGot
+ }
+
+ virtual const DefinedAtom *makeGOTEntry(const Atom &target) {
+ return new TestingGOTAtom(_file, target);
+ }
+
+private:
+ TestingPassFile _file;
+};
+
+} // anonymous namespace
+
+
+CoreTargetInfo::CoreTargetInfo() {
+}
+
+
+void CoreTargetInfo::addPasses(PassManager &pm) const {
+ for (StringRef name : _passNames) {
+ if ( name.equals("layout") )
+ pm.add(std::unique_ptr<Pass>((new LayoutPass())));
+ else if ( name.equals("GOT") )
+ pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
+ else if ( name.equals("stubs") )
+ pm.add(std::unique_ptr<Pass>(new TestingStubsPass(*this)));
+ else
+ llvm_unreachable("bad pass name");
+ }
+}
+
+
+error_code CoreTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
+ if (!_reader)
+ _reader = createReaderYAML(*this);
+ return _reader->parseFile(mb,result);
+}
+
+Writer &CoreTargetInfo::writer() const {
+ if (!_writer)
+ _writer = createWriterYAML(*this);
+ return *_writer;
+}
+
+
+ErrorOr<Reference::Kind>
+CoreTargetInfo::relocKindFromString(StringRef str) const {
+ for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
+ if (str.equals(p->string))
+ return p->value;
+ }
+ return make_error_code(yaml_reader_error::illegal_value);
+}
+
+ErrorOr<std::string>
+CoreTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
+ if (kind == p->value)
+ return std::string(p->string);
+ }
+ return make_error_code(yaml_reader_error::illegal_value);
+}
+
+
+
diff --git a/lld/lib/ReaderWriter/ELF/Atoms.h b/lld/lib/ReaderWriter/ELF/Atoms.h
index c5f66bcdedf..28501d9b231 100644
--- a/lld/lib/ReaderWriter/ELF/Atoms.h
+++ b/lld/lib/ReaderWriter/ELF/Atoms.h
@@ -512,7 +512,8 @@ public:
const Elf_Shdr *section, llvm::ArrayRef<uint8_t> contentData,
uint64_t offset)
: _owningFile(file), _sectionName(sectionName), _section(section),
- _contentData(contentData), _offset(offset) {}
+ _contentData(contentData), _offset(offset) {
+ }
virtual const class ELFFile<ELFT> &file() const {
return _owningFile;
diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
index 73a4c163143..8c520ff4f7e 100644
--- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h
+++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
@@ -16,7 +16,6 @@
#include "SectionChunks.h"
#include "SegmentChunks.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/STDExtras.h"
#include "llvm/ADT/ArrayRef.h"
@@ -28,6 +27,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Format.h"
#include <map>
#include <tuple>
@@ -667,7 +667,6 @@ DefaultLayout<ELFT>::assignVirtualAddress() {
}
firstLoadSegment->prepend(_programHeader);
firstLoadSegment->prepend(_header);
-
bool newSegmentHeaderAdded = true;
while (true) {
for (auto si : _segments) {
diff --git a/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h b/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h
index c6426724f25..c019df1baed 100644
--- a/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h
@@ -13,7 +13,6 @@
#include "DefaultLayout.h"
#include "TargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/ADT/Triple.h"
diff --git a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
index 3395609979c..338096d3a2c 100644
--- a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
@@ -12,41 +12,38 @@
#include "TargetHandler.h"
#include "Targets.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Passes/LayoutPass.h"
#include "lld/ReaderWriter/ReaderLinkerScript.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
namespace lld {
-ELFTargetInfo::ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
-
-uint16_t ELFTargetInfo::getOutputType() const {
- switch (_options._outputKind) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
- return llvm::ELF::ET_EXEC;
- case OutputKind::Relocatable:
- return llvm::ELF::ET_REL;
- case OutputKind::Shared:
- return llvm::ELF::ET_DYN;
- case OutputKind::Core:
- return llvm::ELF::ET_CORE;
- case OutputKind::SharedStubs:
- case OutputKind::DebugSymbols:
- case OutputKind::Bundle:
- case OutputKind::Preload:
- break;
- case OutputKind::Invalid:
- llvm_unreachable("Invalid output kind!");
- }
- llvm_unreachable("Unhandled OutputKind");
+ELFTargetInfo::ELFTargetInfo(llvm::Triple triple)
+ : _outputFileType(elf::ET_EXEC)
+ , _triple(triple)
+ , _baseAddress(0)
+ , _isStaticExecutable(false)
+ , _outputYAML(false)
+ , _noInhibitExec(false)
+ , _mergeCommonStrings(false)
+ , _runLayoutPass(true) {
+}
+
+bool ELFTargetInfo::is64Bits() const {
+ return getTriple().isArch64Bit();
+}
+
+bool ELFTargetInfo::isLittleEndian() const {
+ // TODO: Do this properly. It is not defined purely by arch.
+ return true;
}
void ELFTargetInfo::addPasses(PassManager &pm) const {
- pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+ if (_runLayoutPass)
+ pm.add(std::unique_ptr<Pass>(new LayoutPass()));
}
uint16_t ELFTargetInfo::getOutputMachine() const {
@@ -64,31 +61,63 @@ uint16_t ELFTargetInfo::getOutputMachine() const {
}
}
-ErrorOr<Reader &> ELFTargetInfo::getReader(const LinkerInput &input) const {
- DEBUG_WITH_TYPE("inputs", llvm::dbgs() << input.getPath() << "\n");
- auto buffer = input.getBuffer();
- if (!buffer)
- return error_code(buffer);
- auto magic = llvm::sys::fs::identify_magic(buffer->getBuffer());
- // Assume unknown file types are linker scripts.
- if (magic == llvm::sys::fs::file_magic::unknown) {
- if (!_linkerScriptReader)
- _linkerScriptReader.reset(new ReaderLinkerScript(
- *this,
- std::bind(&ELFTargetInfo::getReader, this, std::placeholders::_1)));
- return *_linkerScriptReader;
+bool ELFTargetInfo::validate(raw_ostream &diagnostics) {
+ if (_outputFileType == elf::ET_EXEC) {
+ if (_entrySymbolName.empty()) {
+ _entrySymbolName = "_start";
+ }
+ }
+
+ if (_inputFiles.empty()) {
+ diagnostics << "No input files\n";
+ return true;
+ }
+
+
+ return false;
+}
+
+
+bool ELFTargetInfo::isDynamic() const {
+ switch (_outputFileType) {
+ case llvm::ELF::ET_EXEC:
+ if (_isStaticExecutable)
+ return false;
+ else
+ return true;
+ case llvm::ELF::ET_DYN:
+ return true;
}
+ return false;
+}
- // Assume anything else is an ELF file.
+
+error_code ELFTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
if (!_elfReader)
- _elfReader = createReaderELF(*this, std::bind(&ELFTargetInfo::getReader,
- this, std::placeholders::_1));
- return *_elfReader;
+ _elfReader = createReaderELF(*this);
+ error_code ec = _elfReader->parseFile(mb, result);
+ if (ec) {
+ // Not an ELF file, check file extension to see if it might be yaml
+ StringRef path = mb->getBufferIdentifier();
+ if ( path.endswith(".objtxt") ) {
+ if (!_yamlReader)
+ _yamlReader = createReaderYAML(*this);
+ ec = _yamlReader->parseFile(mb, result);
+ }
+ if (ec) {
+ // Not a yaml file, assume it is a linkerscript
+ if (!_linkerScriptReader)
+ _linkerScriptReader.reset(new ReaderLinkerScript(*this));
+ ec = _linkerScriptReader->parseFile(mb, result);
+ }
+ }
+ return ec;
}
-ErrorOr<Writer &> ELFTargetInfo::getWriter() const {
+Writer &ELFTargetInfo::writer() const {
if (!_writer) {
- if (_options._outputYAML)
+ if (_outputYAML)
_writer = createWriterYAML(*this);
else
_writer = createWriterELF(*this);
@@ -96,27 +125,40 @@ ErrorOr<Writer &> ELFTargetInfo::getWriter() const {
return *_writer;
}
-std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(const LinkerOptions &lo) {
- switch (llvm::Triple(llvm::Triple::normalize(lo._target)).getArch()) {
+
+std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(llvm::Triple triple) {
+ switch (triple.getArch()) {
case llvm::Triple::x86:
- return std::unique_ptr<ELFTargetInfo>(new lld::elf::X86TargetInfo(lo));
+ return std::unique_ptr<ELFTargetInfo>(new lld::elf::X86TargetInfo(triple));
case llvm::Triple::x86_64:
return std::unique_ptr<
- ELFTargetInfo>(new lld::elf::X86_64TargetInfo(lo));
+ ELFTargetInfo>(new lld::elf::X86_64TargetInfo(triple));
case llvm::Triple::hexagon:
return std::unique_ptr<
- ELFTargetInfo>(new lld::elf::HexagonTargetInfo(lo));
+ ELFTargetInfo>(new lld::elf::HexagonTargetInfo(triple));
case llvm::Triple::ppc:
- return std::unique_ptr<ELFTargetInfo>(new lld::elf::PPCTargetInfo(lo));
+ return std::unique_ptr<ELFTargetInfo>(new lld::elf::PPCTargetInfo(triple));
default:
return std::unique_ptr<ELFTargetInfo>();
}
}
-StringRef ELFTargetInfo::getEntry() const {
- if (!_options._entrySymbol.empty())
- return _options._entrySymbol;
- return "_start";
+bool ELFTargetInfo::appendLibrary(StringRef libName) {
+ SmallString<128> fullPath;
+ for (StringRef dir : _inputSearchPaths) {
+ // FIXME: need to handle other extensions, like .so
+ fullPath.assign(dir);
+ llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
+ StringRef pathref = fullPath.str();
+ unsigned pathlen = pathref.size();
+ if (llvm::sys::fs::exists(pathref)) {
+ char *x = _extraStrings.Allocate<char>(pathlen);
+ memcpy(x, pathref.data(), pathlen);
+ appendInputFile(StringRef(x,pathlen));
+ return false;
+ }
+ }
+ return true;
}
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h
index 4216cd5fb5b..d2ecbb2a903 100644
--- a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h
+++ b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h
@@ -49,6 +49,7 @@ public:
/// \brief add an undefined atom
virtual void addUndefinedAtom(StringRef symbolName) {
+ assert(!symbolName.empty() && "UndefinedAtoms must have a name");
Elf_Sym *symbol = new (_allocator) Elf_Sym;
symbol->st_name = 0;
symbol->st_value = 0;
diff --git a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h
index fc0bde043b8..6bc283d701d 100644
--- a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h
+++ b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h
@@ -46,7 +46,7 @@ private:
/// absolute symbols
template<class ELFT>
void ExecutableWriter<ELFT>::addDefaultAtoms() {
- _runtimeFile.addUndefinedAtom(this->_targetInfo.getEntry());
+ _runtimeFile.addUndefinedAtom(this->_targetInfo.entrySymbolName());
_runtimeFile.addAbsoluteAtom("__bss_start");
_runtimeFile.addAbsoluteAtom("__bss_end");
_runtimeFile.addAbsoluteAtom("_end");
diff --git a/lld/lib/ReaderWriter/ELF/File.h b/lld/lib/ReaderWriter/ELF/File.h
index cbc2fff9895..a4c712420c9 100644
--- a/lld/lib/ReaderWriter/ELF/File.h
+++ b/lld/lib/ReaderWriter/ELF/File.h
@@ -143,7 +143,7 @@ public:
// Sections that have merge string property
std::vector<const Elf_Shdr *> mergeStringSections;
- bool doStringsMerge = _elfTargetInfo.getLinkerOptions()._mergeCommonStrings;
+ bool doStringsMerge = _elfTargetInfo.mergeCommonStrings();
// Handle: SHT_REL and SHT_RELA sections:
// Increment over the sections, when REL/RELA section types are found add
diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
index fe8efddfb0d..64400dc26d0 100644
--- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h
+++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
@@ -18,6 +18,7 @@
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/Format.h"
/// \brief An Header represents the Elf[32/64]_Ehdr structure at the
/// start of an ELF executable file.
@@ -98,10 +99,10 @@ public:
FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear)
: _type(type)
, _flags(flags)
- , _flagsClear(flagsClear)
- {}
+ , _flagsClear(flagsClear) {
+ }
- bool operator()(const Elf_Phdr *j) const {
+ bool operator()(const llvm::object::Elf_Phdr_Impl<ELFT> *j) const {
return ((j->p_type == _type) &&
((j->p_flags & _flags) == _flags) &&
(!(j->p_flags & _flagsClear)));
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h
index b0ee2e440e9..a02caa74595 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h
@@ -29,7 +29,8 @@ typedef struct {
sizeof(insn_encodings_v4) / sizeof(Instruction))
/// \brief finds the scatter Bits that need to be used to apply relocations
-uint32_t findBitMask(uint32_t insn, Instruction *encodings, int32_t numInsns) {
+inline uint32_t
+findBitMask(uint32_t insn, Instruction *encodings, int32_t numInsns) {
for (int32_t i = 0; i < numInsns ; i++) {
if (((insn & 0xc000) == 0) && !(encodings[i].isDuplex))
continue;
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
index d7c15d410a3..cc928e6b379 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
@@ -212,8 +212,7 @@ public:
} // end anonymous namespace
void elf::HexagonTargetInfo::addPasses(PassManager &pm) const {
- if (_options._outputKind == OutputKind::DynamicExecutable ||
- _options._outputKind == OutputKind::Shared)
+ if (isDynamic())
pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
ELFTargetInfo::addPasses(pm);
}
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp
index ddba886525d..49d91434fde 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp
@@ -22,8 +22,8 @@ using namespace lld;
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
-ErrorOr<int32_t> elf::HexagonTargetInfo::relocKindFromString(
- StringRef str) const {
+ErrorOr<Reference::Kind>
+elf::HexagonTargetInfo::relocKindFromString(StringRef str) const {
int32_t ret = llvm::StringSwitch<int32_t>(str)
LLD_CASE(R_HEX_NONE)
LLD_CASE(R_HEX_B22_PCREL)
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h
index ca8fb94d30d..82f4c6b5ce5 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h
@@ -12,7 +12,6 @@
#include "HexagonTargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/Object/ELF.h"
@@ -23,15 +22,14 @@ namespace elf {
class HexagonTargetInfo LLVM_FINAL : public ELFTargetInfo {
public:
- HexagonTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
+ HexagonTargetInfo(llvm::Triple triple)
+ : ELFTargetInfo(triple) {
_targetHandler = std::unique_ptr<TargetHandlerBase>(
new HexagonTargetHandler(*this));
}
- virtual uint64_t getPageSize() const { return 0x1000; }
-
- virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const;
- virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const;
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
virtual void addPasses(PassManager &) const;
diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
index 2cc81dd1462..40f14bb5f03 100644
--- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
+++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
@@ -345,7 +345,7 @@ error_code OutputELFWriter<ELFT>::writeFile(const File &file, StringRef path) {
_Header->e_shnum(_shdrtab->numHeaders());
_Header->e_shstrndx(_shstrtab->ordinal());
uint64_t virtualAddr = 0;
- _layout->findAtomAddrByName(_targetInfo.getEntry(), virtualAddr);
+ _layout->findAtomAddrByName(_targetInfo.entrySymbolName(), virtualAddr);
_Header->e_entry(virtualAddr);
// HACK: We have to write out the header and program header here even though
diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp
index e69de29bb2d..337b02f4c2a 100644
--- a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp
@@ -0,0 +1,36 @@
+#include "PPCTargetInfo.h"
+
+#include "lld/Core/LLVM.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorOr.h"
+
+using namespace lld;
+
+#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
+
+ErrorOr<Reference::Kind> elf::PPCTargetInfo::relocKindFromString(
+ StringRef str) const {
+ int32_t ret = llvm::StringSwitch<int32_t>(str)
+ LLD_CASE(R_PPC_NONE)
+ LLD_CASE(R_PPC_ADDR32)
+ .Default(-1);
+
+ if (ret == -1)
+ return make_error_code(yaml_reader_error::illegal_value);
+ return ret;
+}
+
+#undef LLD_CASE
+
+#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
+
+ErrorOr<std::string>
+elf::PPCTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ switch (kind) {
+ LLD_CASE(R_PPC_NONE)
+ LLD_CASE(R_PPC_ADDR32)
+ }
+
+ return make_error_code(yaml_reader_error::illegal_value);
+}
diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h
index 97ba655d4ab..077767695c9 100644
--- a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h
+++ b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h
@@ -12,7 +12,6 @@
#include "PPCTargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/Object/ELF.h"
@@ -22,14 +21,15 @@ namespace lld {
namespace elf {
class PPCTargetInfo LLVM_FINAL : public ELFTargetInfo {
public:
- PPCTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
+ PPCTargetInfo(llvm::Triple triple)
+ : ELFTargetInfo(triple) {
_targetHandler = std::unique_ptr<TargetHandlerBase>(
new PPCTargetHandler(*this));
}
virtual bool isLittleEndian() const { return false; }
-
- virtual uint64_t getPageSize() const { return 0x1000; }
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
};
} // elf
diff --git a/lld/lib/ReaderWriter/ELF/Reader.cpp b/lld/lib/ReaderWriter/ELF/Reader.cpp
index be2fedb239b..cb6e9cde00f 100644
--- a/lld/lib/ReaderWriter/ELF/Reader.cpp
+++ b/lld/lib/ReaderWriter/ELF/Reader.cpp
@@ -78,12 +78,12 @@ namespace elf {
/// memory buffer for ELF class and bit width
class ELFReader : public Reader {
public:
- ELFReader(const ELFTargetInfo &ti, std::function<ReaderFunc> read)
- : lld::Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, read) {
+ ELFReader(const ELFTargetInfo &ti)
+ : lld::Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, *this) {
}
- error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File> > &result) {
+ error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File> > &result) const {
using llvm::object::ELFType;
llvm::sys::LLVMFileType fileType =
llvm::sys::IdentifyFileType(mb->getBufferStart(),
@@ -112,10 +112,10 @@ public:
break;
}
case llvm::sys::Archive_FileType:
- ec = _readerArchive.parseFile(std::move(mb), result);
+ ec = _readerArchive.parseFile(mb, result);
break;
default:
- llvm_unreachable("not supported format");
+ return llvm::make_error_code(llvm::errc::executable_format_error);
break;
}
@@ -131,8 +131,7 @@ private:
};
} // end namespace elf
-std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &eti,
- std::function<ReaderFunc> read) {
- return std::unique_ptr<Reader>(new elf::ELFReader(eti, std::move(read)));
+std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &targetinfo) {
+ return std::unique_ptr<Reader>(new elf::ELFReader(targetinfo));
}
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h
index 2bca266fe2d..8237529629f 100644
--- a/lld/lib/ReaderWriter/ELF/SectionChunks.h
+++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h
@@ -603,13 +603,13 @@ public:
/// \brief Get the symbol table index for an Atom. If it's not in the symbol
/// table, return STN_UNDEF.
uint32_t getSymbolTableIndex(const Atom *a) const {
- auto se = std::find_if(_symbolTable.begin(), _symbolTable.end(),
+ auto entry = std::find_if(_symbolTable.begin(), _symbolTable.end(),
[=](const SymbolEntry &se) {
return se._atom == a;
});
- if (se == _symbolTable.end())
+ if (entry == _symbolTable.end())
return STN_UNDEF;
- return std::distance(_symbolTable.begin(), se);
+ return std::distance(_symbolTable.begin(), entry);
}
virtual void finalize() { finalize(true); }
diff --git a/lld/lib/ReaderWriter/ELF/TargetHandler.h b/lld/lib/ReaderWriter/ELF/TargetHandler.h
index ebdb203c0da..ab30c3636e7 100644
--- a/lld/lib/ReaderWriter/ELF/TargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/TargetHandler.h
@@ -19,7 +19,6 @@
#include "Layout.h"
#include "lld/Core/InputFiles.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/TargetInfo.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
diff --git a/lld/lib/ReaderWriter/ELF/Writer.cpp b/lld/lib/ReaderWriter/ELF/Writer.cpp
index 6e2744ea1f3..a174ef0c051 100644
--- a/lld/lib/ReaderWriter/ELF/Writer.cpp
+++ b/lld/lib/ReaderWriter/ELF/Writer.cpp
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/ELF/Writer.cpp ------------------------------------===//
+//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
//
// The LLVM Linker
//
@@ -6,53 +6,63 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "ExecutableWriter.h"
+
+#include "lld/ReaderWriter/Writer.h"
+
#include "DynamicLibraryWriter.h"
+#include "ExecutableWriter.h"
+
using namespace llvm;
using namespace llvm::object;
-
namespace lld {
-std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &TI) {
+std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &info) {
using llvm::object::ELFType;
// Set the default layout to be the static executable layout
// We would set the layout to a dynamic executable layout
// if we came across any shared libraries in the process
- const LinkerOptions &options = TI.getLinkerOptions();
-
- if ((options._outputKind == OutputKind::StaticExecutable) ||
- (options._outputKind == OutputKind::DynamicExecutable)) {
- if (!TI.is64Bits() && TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::ExecutableWriter<ELFType<support::little, 4, false>>(TI));
- else if (TI.is64Bits() && TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::ExecutableWriter<ELFType<support::little, 8, true>>(TI));
- else if (!TI.is64Bits() && !TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::ExecutableWriter<ELFType<support::big, 4, false>>(TI));
- else if (TI.is64Bits() && !TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::ExecutableWriter<ELFType<support::big, 8, true>>(TI));
- llvm_unreachable("Invalid Options!");
- } else if (options._outputKind == OutputKind::Shared) {
- if (!TI.is64Bits() && TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::DynamicLibraryWriter<ELFType<support::little, 4, false>>(TI));
- else if (TI.is64Bits() && TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::DynamicLibraryWriter<ELFType<support::little, 8, true>>(TI));
- else if (!TI.is64Bits() && !TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::DynamicLibraryWriter<ELFType<support::big, 4, false>>(TI));
- else if (TI.is64Bits() && !TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::DynamicLibraryWriter<ELFType<support::big, 8, true>>(TI));
- llvm_unreachable("Invalid Options!");
+ switch(info.getOutputType()) {
+ case llvm::ELF::ET_EXEC:
+ if (info.is64Bits()) {
+ if (info.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::little, 8, true>>(info));
+ else
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::big, 8, true>>(info));
+ } else {
+ if (info.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::little, 4, false>>(info));
+ else
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::big, 4, false>>(info));
+ }
+ break;
+ case llvm::ELF::ET_DYN:
+ if (info.is64Bits()) {
+ if (info.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::DynamicLibraryWriter<ELFType<support::little, 8, true>>(info));
+ else
+ return std::unique_ptr<Writer>(new
+ elf::DynamicLibraryWriter<ELFType<support::big, 8, true>>(info));
+ } else {
+ if (info.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::DynamicLibraryWriter<ELFType<support::little, 4, false>>(info));
+ else
+ return std::unique_ptr<Writer>(new
+ elf::DynamicLibraryWriter<ELFType<support::big, 4, false>>(info));
+ }
+ break;
+ case llvm::ELF::ET_REL:
+ llvm_unreachable("TODO: support -r mode");
+ default:
+ llvm_unreachable("unsupported output type");
}
- else
- llvm_unreachable("unsupported options");
-}
}
+
+} // namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/Writer.h b/lld/lib/ReaderWriter/ELF/Writer.h
index 7e67c31369d..20b330ed739 100644
--- a/lld/lib/ReaderWriter/ELF/Writer.h
+++ b/lld/lib/ReaderWriter/ELF/Writer.h
@@ -28,7 +28,7 @@ public:
virtual void buildChunks(const File &file) = 0;
/// \brief Writes the chunks into the output file specified by path
- virtual error_code writeFile(const File &File, StringRef path) = 0;
+ virtual error_code writeFile(const File &file, StringRef path) = 0;
/// \brief Get the virtual address of \p atom after layout.
virtual uint64_t addressOfAtom(const Atom *atom) = 0;
diff --git a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp
index e69de29bb2d..8a0737c5fc8 100644
--- a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp
@@ -0,0 +1,36 @@
+#include "X86TargetInfo.h"
+
+#include "lld/Core/LLVM.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorOr.h"
+
+using namespace lld;
+
+#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
+
+ErrorOr<Reference::Kind> elf::X86TargetInfo::relocKindFromString(
+ StringRef str) const {
+ int32_t ret = llvm::StringSwitch<int32_t>(str)
+ LLD_CASE(R_386_NONE)
+ LLD_CASE(R_386_PC32)
+ .Default(-1);
+
+ if (ret == -1)
+ return make_error_code(yaml_reader_error::illegal_value);
+ return ret;
+}
+
+#undef LLD_CASE
+
+#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
+
+ErrorOr<std::string>
+elf::X86TargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ switch (kind) {
+ LLD_CASE(R_386_NONE)
+ LLD_CASE(R_386_PC32)
+ }
+
+ return make_error_code(yaml_reader_error::illegal_value);
+}
diff --git a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h
index c66a42f78d6..00007afbdf0 100644
--- a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h
+++ b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h
@@ -12,7 +12,6 @@
#include "X86TargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/Object/ELF.h"
@@ -22,12 +21,14 @@ namespace lld {
namespace elf {
class X86TargetInfo LLVM_FINAL : public ELFTargetInfo {
public:
- X86TargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
+ X86TargetInfo(llvm::Triple triple)
+ : ELFTargetInfo(triple) {
_targetHandler = std::unique_ptr<TargetHandlerBase>(
new X86TargetHandler(*this));
}
- virtual uint64_t getPageSize() const { return 0x1000; }
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
};
} // end namespace elf
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
index bb6236e109e..cad8dd2809f 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
@@ -399,18 +399,29 @@ public:
} // end anon namespace
void elf::X86_64TargetInfo::addPasses(PassManager &pm) const {
- if (_options._outputKind == OutputKind::StaticExecutable)
- pm.add(std::unique_ptr<Pass>(new StaticGOTPLTPass(*this)));
- else if (_options._outputKind == OutputKind::DynamicExecutable ||
- _options._outputKind == OutputKind::Shared)
+ switch (_outputFileType) {
+ case llvm::ELF::ET_EXEC:
+ if (_isStaticExecutable)
+ pm.add(std::unique_ptr<Pass>(new StaticGOTPLTPass(*this)));
+ else
+ pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
+ break;
+ case llvm::ELF::ET_DYN:
pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
+ break;
+ case llvm::ELF::ET_REL:
+ break;
+ default:
+ llvm_unreachable("Unhandled output file type");
+ }
ELFTargetInfo::addPasses(pm);
}
+
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
-ErrorOr<int32_t> elf::X86_64TargetInfo::relocKindFromString(
- StringRef str) const {
+ErrorOr<Reference::Kind>
+elf::X86_64TargetInfo::relocKindFromString(StringRef str) const {
int32_t ret = llvm::StringSwitch<int32_t>(str)
LLD_CASE(R_X86_64_NONE)
LLD_CASE(R_X86_64_64)
@@ -462,8 +473,8 @@ ErrorOr<int32_t> elf::X86_64TargetInfo::relocKindFromString(
#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
-ErrorOr<std::string> elf::X86_64TargetInfo::stringFromRelocKind(
- int32_t kind) const {
+ErrorOr<std::string>
+elf::X86_64TargetInfo::stringFromRelocKind(Reference::Kind kind) const {
switch (kind) {
LLD_CASE(R_X86_64_NONE)
LLD_CASE(R_X86_64_64)
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h
index 11adab4ecfc..4c8afa065df 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h
@@ -12,7 +12,6 @@
#include "X86_64TargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/Object/ELF.h"
@@ -29,19 +28,18 @@ enum {
class X86_64TargetInfo LLVM_FINAL : public ELFTargetInfo {
public:
- X86_64TargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
+ X86_64TargetInfo(llvm::Triple triple)
+ : ELFTargetInfo(triple) {
_targetHandler =
std::unique_ptr<TargetHandlerBase>(new X86_64TargetHandler(*this));
}
- virtual uint64_t getPageSize() const { return 0x1000; }
-
virtual void addPasses(PassManager &) const;
virtual uint64_t getBaseAddress() const {
- if (_options._baseAddress == 0)
+ if (_baseAddress == 0)
return 0x400000;
- return _options._baseAddress;
+ return _baseAddress;
}
virtual bool isDynamicRelocation(const DefinedAtom &,
@@ -66,8 +64,8 @@ public:
}
}
- virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const;
- virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const;
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
};
} // end namespace elf
diff --git a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
index de8d5214e43..54dcb69de91 100644
--- a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
+++ b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
@@ -29,13 +29,13 @@ namespace mach_o {
class CRuntimeFile : public SimpleFile {
public:
CRuntimeFile(const MachOTargetInfo &ti)
- : SimpleFile(ti, "C runtime"), _undefMain(*this, "_main") {
+ : SimpleFile(ti, "C runtime"), _undefMain(*this, ti.entrySymbolName()) {
// only main executables need _main
- if (ti.getLinkerOptions()._outputKind == OutputKind::StaticExecutable ||
- ti.getLinkerOptions()._outputKind == OutputKind::DynamicExecutable)
+ if (ti.outputFileType() == MH_EXECUTE) {
this->addAtom(_undefMain);
+ }
}
-
+
private:
SimpleUndefinedAtom _undefMain;
};
diff --git a/lld/lib/ReaderWriter/MachO/MachOFormat.hpp b/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
index 2010a7f87da..41b432a16ec 100644
--- a/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
+++ b/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
@@ -40,12 +40,14 @@ enum {
CPU_SUBTYPE_X86_ALL = 0x00000003,
CPU_SUBTYPE_X86_64_ALL = 0x00000003,
CPU_SUBTYPE_ARM_V6 = 0x00000006,
- CPU_SUBTYPE_ARM_V7 = 0x00000009
+ CPU_SUBTYPE_ARM_V7 = 0x00000009,
+ CPU_SUBTYPE_ARM_V7S = 0x0000000B
};
enum {
MH_OBJECT = 0x1,
MH_EXECUTE = 0x2,
+ MH_PRELOAD = 0x5,
MH_DYLIB = 0x6,
MH_DYLINKER = 0x7,
MH_BUNDLE = 0x8,
@@ -494,7 +496,7 @@ public:
// in-memory matches on-disk, so copy first fields followed by path
::memcpy(to, (uint8_t*)&cmd, 24);
::memcpy(&to[24], _loadPath.data(), _loadPath.size());
- ::memset(&to[12+_loadPath.size()], 0, cmdsize-(12+_loadPath.size()));
+ ::memset(&to[24+_loadPath.size()], 0, cmdsize-(24+_loadPath.size()));
}
}
diff --git a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
index 0b2d0772294..f60f32ea43c 100644
--- a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
@@ -10,83 +10,244 @@
#include "lld/ReaderWriter/MachOTargetInfo.h"
#include "GOTPass.hpp"
#include "StubsPass.hpp"
+#include "ReferenceKinds.h"
+#include "MachOFormat.hpp"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/PassManager.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/Writer.h"
#include "lld/Passes/LayoutPass.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/MachO.h"
+
+using lld::mach_o::KindHandler;
+
namespace lld {
+
+
+MachOTargetInfo::PackedVersion::PackedVersion(StringRef str) {
+ if (parse(str, *this))
+ llvm_unreachable("bad version string");
+}
+
+/// Construct 32-bit PackedVersion from string "X.Y.Z" where
+/// bits are xxxx.yy.zz. Largest number is 65535.255.255
+bool MachOTargetInfo::PackedVersion::parse(StringRef str,
+ MachOTargetInfo::PackedVersion &result) {
+ result._value = 0;
+
+ if (str.empty())
+ return false;
+
+ SmallVector<StringRef, 3> parts;
+ llvm::SplitString(str, parts, ".");
+
+ unsigned long long num;
+ if (llvm::getAsUnsignedInteger(parts[0], 10, num))
+ return true;
+ if (num > 65535)
+ return true;
+ result._value = num << 16;
+
+ if (parts.size() > 1) {
+ if (llvm::getAsUnsignedInteger(parts[1], 10, num))
+ return true;
+ if (num > 255)
+ return true;
+ result._value |= (num << 8);
+ }
+
+ if (parts.size() > 2) {
+ if (llvm::getAsUnsignedInteger(parts[2], 10, num))
+ return true;
+ if (num > 255)
+ return true;
+ result._value |= num;
+ }
+
+ return false;
+}
+
+bool MachOTargetInfo::PackedVersion::operator<(
+ const PackedVersion &rhs) const {
+ return _value < rhs._value;
+}
+
+bool MachOTargetInfo::PackedVersion::operator>=(
+ const PackedVersion &rhs) const {
+ return _value >= rhs._value;
+}
+
+bool MachOTargetInfo::PackedVersion::operator==(
+ const PackedVersion &rhs) const {
+ return _value == rhs._value;
+}
+
+
+MachOTargetInfo::MachOTargetInfo()
+ : _outputFileType(mach_o::MH_EXECUTE)
+ , _outputFileTypeStatic(false)
+ , _arch(arch_unknown)
+ , _os(OS::macOSX)
+ , _osMinVersion("0.0")
+ , _pageZeroSize(0x1000)
+ , _kindHandler(nullptr) {
+}
+
+
+MachOTargetInfo::~MachOTargetInfo() {
+}
+
uint32_t MachOTargetInfo::getCPUType() const {
- switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- return llvm::MachO::CPUTypeI386;
- case llvm::Triple::x86_64:
- return llvm::MachO::CPUTypeX86_64;
- case llvm::Triple::arm:
- return llvm::MachO::CPUTypeARM;
- default:
+ switch (_arch) {
+ case MachOTargetInfo::arch_x86:
+ return mach_o::CPU_TYPE_I386;
+ case MachOTargetInfo::arch_x86_64:
+ return mach_o::CPU_TYPE_X86_64;
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
+ return mach_o::CPU_TYPE_ARM;
+ case MachOTargetInfo::arch_unknown:
llvm_unreachable("Unknown arch type");
}
}
uint32_t MachOTargetInfo::getCPUSubType() const {
- switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- return llvm::MachO::CPUSubType_I386_ALL;
- case llvm::Triple::x86_64:
- return llvm::MachO::CPUSubType_X86_64_ALL;
- case llvm::Triple::arm:
- return llvm::MachO::CPUSubType_ARM_ALL;
- default:
+ switch (_arch) {
+ case MachOTargetInfo::arch_x86:
+ return mach_o::CPU_SUBTYPE_X86_ALL;
+ case MachOTargetInfo::arch_x86_64:
+ return mach_o::CPU_SUBTYPE_X86_64_ALL;
+ case MachOTargetInfo::arch_armv6:
+ return mach_o::CPU_SUBTYPE_ARM_V6;
+ case MachOTargetInfo::arch_armv7:
+ return mach_o::CPU_SUBTYPE_ARM_V7;
+ case MachOTargetInfo::arch_armv7s:
+ return mach_o::CPU_SUBTYPE_ARM_V7S;
+ case MachOTargetInfo::arch_unknown:
llvm_unreachable("Unknown arch type");
}
}
-bool MachOTargetInfo::addEntryPointLoadCommand() const {
- switch (_options._outputKind) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
+
+bool MachOTargetInfo::outputTypeHasEntry() const {
+ switch (_outputFileType) {
+ case mach_o::MH_EXECUTE:
+ case mach_o::MH_DYLINKER:
+ case mach_o::MH_PRELOAD:
return true;
default:
return false;
}
}
+
+bool MachOTargetInfo::minOS(StringRef mac, StringRef iOS) const {
+ switch (_os) {
+ case OS::macOSX:
+ return (_osMinVersion >= PackedVersion(mac));
+ case OS::iOS:
+ case OS::iOS_simulator:
+ return (_osMinVersion >= PackedVersion(iOS));
+ }
+ llvm_unreachable("target not configured for iOS or MacOSX");
+}
+
+bool MachOTargetInfo::addEntryPointLoadCommand() const {
+ if ((_outputFileType == mach_o::MH_EXECUTE) && !_outputFileTypeStatic) {
+ return minOS("10.8", "6.0");
+ }
+ return false;
+}
+
bool MachOTargetInfo::addUnixThreadLoadCommand() const {
- switch (_options._outputKind) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
+ switch (_outputFileType) {
+ case mach_o::MH_EXECUTE:
+ if (_outputFileTypeStatic)
+ return true;
+ else
+ return !minOS("10.8", "6.0");
+ break;
+ case mach_o::MH_DYLINKER:
+ case mach_o::MH_PRELOAD:
return true;
default:
return false;
}
}
-class GenericMachOTargetInfo LLVM_FINAL : public MachOTargetInfo {
-public:
- GenericMachOTargetInfo(const LinkerOptions &lo) : MachOTargetInfo(lo) {}
+bool MachOTargetInfo::validate(raw_ostream &diagnostics) {
+ if ((_outputFileType == mach_o::MH_EXECUTE) && _entrySymbolName.empty()) {
+ if (_outputFileTypeStatic) {
+ _entrySymbolName = "start";
+ }
+ else {
+ // If targeting newer OS, use _main
+ if (addEntryPointLoadCommand())
+ _entrySymbolName = "_main";
- virtual uint64_t getPageSize() const { return 0x1000; }
- virtual uint64_t getPageZeroSize() const { return getPageSize(); }
-
- virtual StringRef getEntry() const {
- if (!_options._entrySymbol.empty())
- return _options._entrySymbol;
- return "_main";
+ // If targeting older OS, use start (in crt1.o)
+ if (addUnixThreadLoadCommand())
+ _entrySymbolName = "start";
+ }
}
- virtual void addPasses(PassManager &pm) const {
- pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
- pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
- pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+ return false;
+}
+
+bool MachOTargetInfo::setOS(OS os, StringRef minOSVersion) {
+ _os = os;
+ return PackedVersion::parse(minOSVersion, _osMinVersion);
+}
+
+void MachOTargetInfo::addPasses(PassManager &pm) const {
+ pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
+ pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
+ pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+}
+
+
+
+error_code MachOTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
+// if (!_machoReader)
+// _machoReader = createReaderMachO(*this);
+// error_code ec = _machoReader->parseFile(mb,result);
+// if (ec) {
+ if (!_yamlReader)
+ _yamlReader = createReaderYAML(*this);
+ return _yamlReader->parseFile(mb,result);
+// }
+
+ return error_code::success();
+}
+
+
+Writer &MachOTargetInfo::writer() const {
+ if (!_writer) {
+ _writer = createWriterMachO(*this);
}
-};
+ return *_writer;
+}
+
+KindHandler &MachOTargetInfo::kindHandler() const {
+ if (!_kindHandler)
+ _kindHandler = KindHandler::create(_arch);
+ return *_kindHandler;
+}
-std::unique_ptr<MachOTargetInfo>
-MachOTargetInfo::create(const LinkerOptions &lo) {
- return std::unique_ptr<MachOTargetInfo>(new GenericMachOTargetInfo(lo));
+ErrorOr<Reference::Kind>
+MachOTargetInfo::relocKindFromString(StringRef str) const {
+ return kindHandler().stringToKind(str);
+ }
+
+ErrorOr<std::string>
+MachOTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ return std::string(kindHandler().kindToString(kind));
}
+
+
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
index d2fb6177f4f..d2ad3a23b67 100644
--- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
@@ -10,6 +10,7 @@
#include "ReferenceKinds.h"
+
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
@@ -29,14 +30,17 @@ KindHandler::KindHandler() {
KindHandler::~KindHandler() {
}
-KindHandler *KindHandler::makeHandler(llvm::Triple::ArchType arch) {
+std::unique_ptr<mach_o::KindHandler> KindHandler::create(
+ MachOTargetInfo::Arch arch) {
switch( arch ) {
- case llvm::Triple::x86_64:
- return new KindHandler_x86_64();
- case llvm::Triple::x86:
- return new KindHandler_x86();
- case llvm::Triple::arm:
- return new KindHandler_arm();
+ case MachOTargetInfo::arch_x86_64:
+ return std::unique_ptr<mach_o::KindHandler>(new KindHandler_x86_64());
+ case MachOTargetInfo::arch_x86:
+ return std::unique_ptr<mach_o::KindHandler>(new KindHandler_x86());
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
+ return std::unique_ptr<mach_o::KindHandler>(new KindHandler_arm());
default:
llvm_unreachable("Unknown arch");
}
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
index 1fce85ff4e9..a9bf0e658c8 100644
--- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
@@ -10,6 +10,7 @@
#include "lld/Core/LLVM.h"
#include "lld/Core/Reference.h"
+#include "lld/ReaderWriter/MachOTargetInfo.h"
#include "llvm/ADT/Triple.h"
@@ -29,7 +30,7 @@ class KindHandler {
public:
typedef Reference::Kind Kind;
- static KindHandler *makeHandler(llvm::Triple::ArchType arch);
+ static std::unique_ptr<mach_o::KindHandler> create(MachOTargetInfo::Arch);
virtual ~KindHandler();
virtual Kind stringToKind(StringRef str) = 0;
virtual StringRef kindToString(Kind) = 0;
diff --git a/lld/lib/ReaderWriter/MachO/StubsPass.hpp b/lld/lib/ReaderWriter/MachO/StubsPass.hpp
index 64524945625..558fe13e91c 100644
--- a/lld/lib/ReaderWriter/MachO/StubsPass.hpp
+++ b/lld/lib/ReaderWriter/MachO/StubsPass.hpp
@@ -13,7 +13,6 @@
#include "llvm/ADT/DenseMap.h"
#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
@@ -31,7 +30,7 @@ class StubsPass : public lld::StubsPass {
public:
StubsPass(const MachOTargetInfo &ti)
: _targetInfo(ti)
- , _kindHandler(KindHandler::makeHandler(_targetInfo.getTriple().getArch()))
+ , _kindHandler(_targetInfo.kindHandler())
, _file(ti)
, _helperCommonAtom(nullptr)
, _helperCacheAtom(nullptr)
@@ -39,11 +38,11 @@ public:
}
virtual bool noTextRelocs() {
- return !_targetInfo.getLinkerOptions()._textRelocations;
+ return true;
}
virtual bool isCallSite(int32_t kind) {
- return _kindHandler->isCallSite(kind);
+ return _kindHandler.isCallSite(kind);
}
virtual const DefinedAtom* getStub(const Atom& target) {
@@ -60,15 +59,17 @@ public:
}
const DefinedAtom* makeStub(const Atom& target) {
- switch (_targetInfo.getTriple().getArch()) {
- case llvm::Triple::x86_64:
+ switch (_targetInfo.arch()) {
+ case MachOTargetInfo::arch_x86_64:
return makeStub_x86_64(target);
- case llvm::Triple::x86:
+ case MachOTargetInfo::arch_x86:
return makeStub_x86(target);
- case llvm::Triple::arm:
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
return makeStub_arm(target);
default:
- llvm_unreachable("Unknown arch");
+ llvm_unreachable("Unknown mach-o arch");
}
}
@@ -153,7 +154,7 @@ private:
};
const MachOTargetInfo &_targetInfo;
- KindHandler *_kindHandler;
+ mach_o::KindHandler &_kindHandler;
File _file;
llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
std::vector<const DefinedAtom*> _lazyPointers;
diff --git a/lld/lib/ReaderWriter/MachO/WriterMachO.cpp b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
index b0e5fd290e4..e91a3d945c9 100644
--- a/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
+++ b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
@@ -28,7 +28,6 @@
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/InputFiles.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/Reference.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/ReaderWriter/MachOTargetInfo.h"
@@ -155,7 +154,6 @@ public:
uint64_t loadCommandsSize();
private:
- uint32_t filetype(OutputKind);
uint32_t magic(uint32_t cpuType);
mach_header _mh;
@@ -350,7 +348,7 @@ public:
uint64_t *segStartAddr, uint64_t *segEndAddr);
const std::vector<Chunk*> chunks() { return _chunks; }
- KindHandler *kindHandler() { return _referenceKindHandler; }
+ mach_o::KindHandler &kindHandler() { return _referenceKindHandler; }
bool use64BitMachO() const;
@@ -372,7 +370,7 @@ private:
typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
const MachOTargetInfo &_targetInfo;
- KindHandler *_referenceKindHandler;
+ mach_o::KindHandler &_referenceKindHandler;
CRuntimeFile _cRuntimeFile;
LoadCommandsChunk *_loadCommandsChunk;
LoadCommandPaddingChunk *_paddingChunk;
@@ -580,7 +578,7 @@ void SectionChunk::write(uint8_t *chunkBuffer) {
if ( ref->target() != nullptr )
targetAddress = _writer.addressOfAtom(ref->target());
uint64_t fixupAddress = _writer.addressOfAtom(atomInfo.atom) + offset;
- _writer.kindHandler()->applyFixup(ref->kind(), ref->addend(),
+ _writer.kindHandler().applyFixup(ref->kind(), ref->addend(),
&atomContent[offset], fixupAddress, targetAddress);
}
}
@@ -596,7 +594,7 @@ MachHeaderChunk::MachHeaderChunk(const MachOTargetInfo &ti, const File &file) {
_mh.magic = this->magic(ti.getCPUType());
_mh.cputype = ti.getCPUType();
_mh.cpusubtype = ti.getCPUSubType();
- _mh.filetype = this->filetype(ti.getLinkerOptions()._outputKind);
+ _mh.filetype = ti.outputFileType();
_mh.ncmds = 0;
_mh.sizeofcmds = 0;
_mh.flags = 0;
@@ -638,30 +636,6 @@ uint32_t MachHeaderChunk::magic(uint32_t cpuType) {
return 0;
}
-uint32_t MachHeaderChunk::filetype(OutputKind kind) {
- switch ( kind ) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
- return MH_EXECUTE;
- case OutputKind::Relocatable:
- return MH_OBJECT;
- case OutputKind::Shared:
- return MH_DYLIB;
- case OutputKind::SharedStubs:
- return MH_DYLIB_STUB;
- case OutputKind::Bundle:
- return MH_BUNDLE;
- case OutputKind::Preload:
- case OutputKind::DebugSymbols:
- case OutputKind::Core:
- break;
- case OutputKind::Invalid:
- llvm_unreachable("Invalid output kind!");
- }
- llvm_unreachable("file OutputKind not supported");
- return 0;
-}
-
//===----------------------------------------------------------------------===//
@@ -719,7 +693,7 @@ uint32_t LoadCommandsChunk::permissionsFromSections(
void LoadCommandsChunk::computeSize(const lld::File &file) {
const bool is64 = _writer.use64BitMachO();
// Main executables have a __PAGEZERO segment.
- uint64_t pageZeroSize = _targetInfo.getPageZeroSize();
+ uint64_t pageZeroSize = _targetInfo.pageZeroSize();
if ( pageZeroSize != 0 ) {
assert(is64 || (pageZeroSize < 0xFFFFFFFF));
segment_command* pzSegCmd = new segment_command(0, is64);
@@ -1032,7 +1006,7 @@ void BindingInfoChunk::computeSize(const lld::File &file,
const SharedLibraryAtom *shlTarget
= dyn_cast<SharedLibraryAtom>(target);
if ( shlTarget != nullptr ) {
- assert(_writer.kindHandler()->isPointer(ref->kind()));
+ assert(_writer.kindHandler().isPointer(ref->kind()));
targetName = shlTarget->name();
ordinal = 1; // FIXME
}
@@ -1099,14 +1073,14 @@ const char* LazyBindingInfoChunk::info() {
void LazyBindingInfoChunk::updateHelper(const DefinedAtom *lazyPointerAtom,
uint32_t offset) {
for (const Reference *ref : *lazyPointerAtom ) {
- if ( ! _writer.kindHandler()->isPointer(ref->kind() ) )
+ if ( ! _writer.kindHandler().isPointer(ref->kind() ) )
continue;
const Atom *targ = ref->target();
const DefinedAtom *helperAtom = dyn_cast<DefinedAtom>(targ);
assert(helperAtom != nullptr);
// Found helper atom. Search it for Reference that is lazy immediate value.
for (const Reference *href : *helperAtom ) {
- if ( _writer.kindHandler()->isLazyImmediate(href->kind()) ) {
+ if ( _writer.kindHandler().isLazyImmediate(href->kind()) ) {
(const_cast<Reference*>(href))->setAddend(offset);
return;
}
@@ -1156,7 +1130,7 @@ void LazyBindingInfoChunk::computeSize(const lld::File &file,
int flags = 0;
StringRef name;
for (const Reference *ref : *lazyPointerAtom ) {
- if ( _writer.kindHandler()->isLazyTarget(ref->kind()) ) {
+ if ( _writer.kindHandler().isLazyTarget(ref->kind()) ) {
const Atom *shlib = ref->target();
assert(shlib != nullptr);
name = shlib->name();
@@ -1301,7 +1275,7 @@ uint32_t SymbolStringsChunk::stringIndex(StringRef str) {
MachOWriter::MachOWriter(const MachOTargetInfo &ti)
: _targetInfo(ti),
- _referenceKindHandler(KindHandler::makeHandler(ti.getTriple().getArch())),
+ _referenceKindHandler(ti.kindHandler()),
_cRuntimeFile(ti),
_bindingInfo(nullptr), _lazyBindingInfo(nullptr),
_symbolTableChunk(nullptr), _stringsChunk(nullptr), _entryAtom(nullptr),
@@ -1392,17 +1366,14 @@ void MachOWriter::addLinkEditChunk(LinkEditChunk *chunk) {
void MachOWriter::buildAtomToAddressMap() {
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
<< "assign atom addresses:\n");
- const bool lookForEntry = _targetInfo.getLinkerOptions()._outputKind ==
- OutputKind::StaticExecutable ||
- _targetInfo.getLinkerOptions()._outputKind ==
- OutputKind::DynamicExecutable;
+ const bool lookForEntry = _targetInfo.outputTypeHasEntry();
for (SectionChunk *chunk : _sectionChunks ) {
for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
_atomToAddress[info.atom] = chunk->address() + info.offsetInSection;
if ( lookForEntry
&& (info.atom->contentType() == DefinedAtom::typeCode)
&& (info.atom->size() != 0)
- && info.atom->name() == _targetInfo.getEntry()) {
+ && info.atom->name() == _targetInfo.entrySymbolName()) {
_entryAtom = info.atom;
}
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
@@ -1425,7 +1396,7 @@ void MachOWriter::assignFileOffsets() {
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
<< "assign file offsets:\n");
uint64_t offset = 0;
- uint64_t address = _targetInfo.getPageZeroSize();
+ uint64_t address = _targetInfo.pageZeroSize();
for ( Chunk *chunk : _chunks ) {
if ( chunk->segmentName().equals("__LINKEDIT") ) {
_linkEditStartOffset = Chunk::alignTo(offset, 12);
@@ -1463,7 +1434,7 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
const uint64_t kInvalidAddress = (uint64_t)(-1);
StringRef lastSegName("__TEXT");
*segIndex = 0;
- if ( _targetInfo.getPageZeroSize() != 0 ) {
+ if ( _targetInfo.pageZeroSize() != 0 ) {
*segIndex = 1;
}
*segStartAddr = kInvalidAddress;
@@ -1487,7 +1458,17 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
}
bool MachOWriter::use64BitMachO() const {
- return _targetInfo.getTriple().isArch64Bit();
+ switch (_targetInfo.arch()) {
+ case MachOTargetInfo::arch_x86_64:
+ return true;
+ case MachOTargetInfo::arch_x86:
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
+ return false;
+ default:
+ llvm_unreachable("Unknown mach-o arch");
+ }
}
diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
index 1255a22ee27..ac3cf3bfe41 100644
--- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp
+++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
@@ -916,8 +916,8 @@ public:
: lld::Reader(ti) {}
virtual error_code parseFile(
- std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<lld::File> > &result) {
+ std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<lld::File> > &result) const {
return File::make(_targetInfo, mb, mb->getBufferIdentifier(), result);
}
};
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index 9b33dafccbc..b752a794117 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -369,8 +369,8 @@ class ReaderCOFF : public Reader {
public:
ReaderCOFF(const TargetInfo &ti) : Reader(ti) {}
- error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File> > &result) {
+ error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File> > &result) const {
llvm::error_code ec;
std::unique_ptr<File> f(new FileCOFF(_targetInfo, std::move(mb), ec));
if (ec) {
diff --git a/lld/lib/ReaderWriter/Reader.cpp b/lld/lib/ReaderWriter/Reader.cpp
index 17ee4f3023d..9f08ed27436 100644
--- a/lld/lib/ReaderWriter/Reader.cpp
+++ b/lld/lib/ReaderWriter/Reader.cpp
@@ -19,12 +19,12 @@ Reader::~Reader() {
}
error_code Reader::readFile(StringRef path,
- std::vector<std::unique_ptr<File>> &result) {
+ std::vector<std::unique_ptr<File>> &result) const {
OwningPtr<llvm::MemoryBuffer> opmb;
if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb))
return ec;
std::unique_ptr<MemoryBuffer> mb(opmb.take());
- return this->parseFile(std::move(mb), result);
+ return this->parseFile(mb, result);
}
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/ReaderArchive.cpp b/lld/lib/ReaderWriter/ReaderArchive.cpp
index 370348b8990..d3287dd429d 100644
--- a/lld/lib/ReaderWriter/ReaderArchive.cpp
+++ b/lld/lib/ReaderWriter/ReaderArchive.cpp
@@ -10,7 +10,6 @@
#include "lld/ReaderWriter/ReaderArchive.h"
#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/LinkerOptions.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Object/ObjectFile.h"
@@ -46,8 +45,10 @@ public:
OwningPtr<MemoryBuffer> buff;
if (ci->getMemoryBuffer(buff, true))
return nullptr;
- LinkerInput li(std::unique_ptr<MemoryBuffer>(buff.take()));
- if (_getReader(li)->parseFile(li.takeBuffer(), result))
+ std::unique_ptr<MemoryBuffer> mb(buff.take());
+ if (_targetInfo.logInputFiles())
+ llvm::outs() << buff->getBufferIdentifier() << "\n";
+ if (_targetInfo.parseFile(mb, result))
return nullptr;
assert(result.size() == 1);
@@ -121,8 +122,7 @@ protected:
}
private:
- std::function<ErrorOr<Reader&> (const LinkerInput &)> _getReader;
- std::unique_ptr<llvm::object::Archive> _archive;
+ std::unique_ptr<llvm::object::Archive> _archive;
atom_collection_vector<DefinedAtom> _definedAtoms;
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
@@ -132,10 +132,8 @@ private:
public:
/// only subclasses of ArchiveLibraryFile can be instantiated
FileArchive(const TargetInfo &ti,
- std::function<ErrorOr<Reader &>(const LinkerInput &)> getReader,
std::unique_ptr<llvm::MemoryBuffer> mb, error_code &ec)
- : ArchiveLibraryFile(ti, mb->getBufferIdentifier()),
- _getReader(getReader) {
+ : ArchiveLibraryFile(ti, mb->getBufferIdentifier()) {
std::unique_ptr<llvm::object::Archive> archive_obj(
new llvm::object::Archive(mb.release(), ec));
if (ec)
@@ -155,16 +153,17 @@ public:
}
}
- std::unordered_map<StringRef, llvm::object::Archive::child_iterator> _symbolMemberMap;
+ std::unordered_map<StringRef,
+ llvm::object::Archive::child_iterator> _symbolMemberMap;
}; // class FileArchive
// Returns a vector of Files that are contained in the archive file
// pointed to by the MemoryBuffer
-error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
- std::vector<std::unique_ptr<File>> &result){
+error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
error_code ec;
- if (_options._forceLoadArchives) {
+ if (_targetInfo.forceLoadAllArchives()) {
_archive.reset(new llvm::object::Archive(mb.release(), ec));
if (ec)
return ec;
@@ -174,13 +173,15 @@ error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
OwningPtr<MemoryBuffer> buff;
if ((ec = mf->getMemoryBuffer(buff, true)))
return ec;
- LinkerInput li(std::unique_ptr<MemoryBuffer>(buff.take()));
- if ((ec = _getReader(li)->parseFile(li.takeBuffer(), result)))
+ std::unique_ptr<MemoryBuffer> mbc(buff.take());
+ if (_targetInfo.logInputFiles())
+ llvm::outs() << buff->getBufferIdentifier() << "\n";
+ if ((ec = _targetInfo.parseFile(mbc, result)))
return ec;
}
} else {
std::unique_ptr<File> f;
- f.reset(new FileArchive(_targetInfo, _getReader, std::move(mb), ec));
+ f.reset(new FileArchive(_targetInfo, std::move(mb), ec));
if (ec)
return ec;
diff --git a/lld/lib/ReaderWriter/ReaderLinkerScript.cpp b/lld/lib/ReaderWriter/ReaderLinkerScript.cpp
index 4beb32a3bc6..646f97e7f46 100644
--- a/lld/lib/ReaderWriter/ReaderLinkerScript.cpp
+++ b/lld/lib/ReaderWriter/ReaderLinkerScript.cpp
@@ -11,7 +11,6 @@
#include "lld/Core/Error.h"
#include "lld/Core/File.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/LinkerScript.h"
using namespace lld;
@@ -81,8 +80,8 @@ private:
namespace lld {
error_code
-ReaderLinkerScript::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
- std::vector<std::unique_ptr<File> > &result) {
+ReaderLinkerScript::parseFile(std::unique_ptr<llvm::MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File> > &result) const {
auto lsf = LinkerScriptFile::create(_targetInfo, std::move(mb));
if (!lsf)
return lsf;
@@ -91,10 +90,7 @@ ReaderLinkerScript::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
for (const auto &c : ls->_commands) {
if (auto group = dyn_cast<Group>(c))
for (const auto &path : group->getPaths()) {
- auto reader = _getReader(LinkerInput(path._path));
- if (!reader)
- return reader;
- if (error_code ec = reader->readFile(path._path, result))
+ if (error_code ec = _targetInfo.readFile(path._path, result))
return ec;
}
}
diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index c2945f719f7..5100d3a1547 100644
--- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -288,16 +288,44 @@ struct ScalarTraits<RefKind> {
llvm::raw_ostream &out) {
assert(ctxt != nullptr);
ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt);
- auto relocStr = info->_targetInfo.stringFromRelocKind(value);
- out << (relocStr ? *relocStr : "<unknown>");
- }
+ switch (value) {
+ case lld::Reference::kindLayoutAfter:
+ out << "layout-after";
+ break;
+ case lld::Reference::kindLayoutBefore:
+ out << "layout-before";
+ break;
+ case lld::Reference::kindInGroup:
+ out << "in-group";
+ break;
+ default:
+ if (auto relocStr = info->_targetInfo.stringFromRelocKind(value))
+ out << *relocStr;
+ else
+ out << "<unknown>";
+ break;
+ }
+ }
static StringRef input(StringRef scalar, void *ctxt, RefKind &value) {
assert(ctxt != nullptr);
ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt);
auto relocKind = info->_targetInfo.relocKindFromString(scalar);
- if (!relocKind)
+ if (!relocKind) {
+ if (scalar.equals("layout-after")) {
+ value = lld::Reference::kindLayoutAfter;
+ return StringRef();
+ }
+ if (scalar.equals("layout-before")) {
+ value = lld::Reference::kindLayoutBefore;
+ return StringRef();
+ }
+ if (scalar.equals("in-group")) {
+ value = lld::Reference::kindInGroup;
+ return StringRef();
+ }
return "Invalid relocation kind";
+ }
value = *relocKind;
return StringRef();
}
@@ -1314,8 +1342,8 @@ class ReaderYAML : public Reader {
public:
ReaderYAML(const TargetInfo &ti) : Reader(ti) {}
- error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File>> &result) {
+ error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
// Note: we do not take ownership of the MemoryBuffer. That is
// because yaml may produce multiple File objects, so there is no
// *one* File to take ownership. Therefore, the yaml File objects
OpenPOWER on IntegriCloud