summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2012-04-18 21:55:06 +0000
committerNick Kledzik <kledzik@apple.com>2012-04-18 21:55:06 +0000
commitbb963dfb7ebeab75764e962734c88aca44422dbf (patch)
treecc27be9a8272806d858158c0cdb1104235c6e855 /lld/lib
parenteb1c2bdc1f55fbc5d1e7bb86e9f0e038b0f5adb7 (diff)
downloadbcm5719-llvm-bb963dfb7ebeab75764e962734c88aca44422dbf.tar.gz
bcm5719-llvm-bb963dfb7ebeab75764e962734c88aca44422dbf.zip
Factor out core linking options from Platform in a new ResolverOptions
class. Change Resolver to no longer use Platform. Core linking now issues errors directly. We need to factor that out later. Rework how Darwin executable writer finds "main" atom. It now adds to core linking an Atom which has a Reference to "main". llvm-svn: 155060
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/Core/File.cpp4
-rw-r--r--lld/lib/Core/Resolver.cpp146
-rw-r--r--lld/lib/Core/SymbolTable.cpp55
-rw-r--r--lld/lib/Core/YamlKeyValues.cpp2
-rw-r--r--lld/lib/Core/YamlWriter.cpp5
-rw-r--r--lld/lib/Platforms/Darwin/DarwinPlatform.cpp116
-rw-r--r--lld/lib/Platforms/Darwin/DarwinPlatform.h32
-rw-r--r--lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp1
-rw-r--r--lld/lib/Platforms/Darwin/ExecutableAtoms.hpp84
-rw-r--r--lld/lib/Platforms/Darwin/ExecutableWriter.cpp7
-rw-r--r--lld/lib/Platforms/Darwin/SimpleAtoms.hpp247
-rw-r--r--lld/lib/Platforms/Darwin/StubAtoms.hpp163
12 files changed, 456 insertions, 406 deletions
diff --git a/lld/lib/Core/File.cpp b/lld/lib/Core/File.cpp
index 70ce886919a..768f1d26282 100644
--- a/lld/lib/Core/File.cpp
+++ b/lld/lib/Core/File.cpp
@@ -18,8 +18,4 @@ StringRef File::translationUnitSource() const {
return StringRef();
}
-const Atom *File::entryPoint() const {
- return nullptr;
-}
-
}
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index 0cf5838bb1f..a758a8628ab 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -13,11 +13,11 @@
#include "lld/Core/File.h"
#include "lld/Core/InputFiles.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/SymbolTable.h"
#include "lld/Core/UndefinedAtom.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
@@ -63,17 +63,6 @@ private:
};
-
-
-void Resolver::initializeState() {
- _platform.initialize();
-}
-
-// add initial undefines from -u option
-void Resolver::addInitialUndefines() {
-
-}
-
// add all atoms from all initial .o files
void Resolver::buildInitialAtomList() {
// each input files contributes initial atoms
@@ -86,8 +75,6 @@ void Resolver::buildInitialAtomList() {
// called before the first atom in any file is added with doAtom()
void Resolver::doFile(const File &file) {
- // notify platform
- _platform.fileAdded(file);
}
@@ -102,35 +89,19 @@ void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
// called on each atom when a file is added
void Resolver::doDefinedAtom(const DefinedAtom &atom) {
- // notify platform
- _platform.atomAdded(atom);
-
// add to list of known atoms
_atoms.push_back(&atom);
- // adjust scope (e.g. force some globals to be hidden)
- _platform.adjustScope(atom);
-
// non-static atoms need extra handling
if (atom.scope() != DefinedAtom::scopeTranslationUnit) {
// tell symbol table about non-static atoms
_symbolTable.add(atom);
-
- // platform can add aliases for any symbol
- std::vector<const DefinedAtom *> aliases;
- if (_platform.getAliasAtoms(atom, aliases))
- this->addAtoms(aliases);
}
-
- if (_platform.deadCodeStripping()) {
+
+ if (_options.deadCodeStripping()) {
// add to set of dead-strip-roots, all symbols that
// the compiler marks as don't strip
- if (!atom.deadStrip())
- _deadStripRoots.insert(&atom);
-
- // add to set of dead-strip-roots, all symbols that
- // the platform decided must remain
- if (_platform.isDeadStripRoot(atom))
+ if (atom.deadStrip() == DefinedAtom::deadStripNever)
_deadStripRoots.insert(&atom);
}
}
@@ -165,9 +136,9 @@ void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
// if so, keep searching libraries until no more atoms being added
void Resolver::resolveUndefines() {
const bool searchArchives =
- _platform.searchArchivesToOverrideTentativeDefinitions();
+ _options.searchArchivesToOverrideTentativeDefinitions();
const bool searchDylibs =
- _platform.searchSharedLibrariesToOverrideTentativeDefinitions();
+ _options.searchSharedLibrariesToOverrideTentativeDefinitions();
// keep looping until no more undefines were added in last loop
unsigned int undefineGenCount = 0xFFFFFFFF;
@@ -180,14 +151,6 @@ void Resolver::resolveUndefines() {
// load for previous undefine may also have loaded this undefine
if (!_symbolTable.isDefined(undefName)) {
_inputFiles.searchLibraries(undefName, true, true, false, *this);
-
- // give platform a chance to instantiate platform
- // specific atoms (e.g. section boundary)
- if (!_symbolTable.isDefined(undefName)) {
- std::vector<const DefinedAtom *> platAtoms;
- if (_platform.getPlatformAtoms(undefName, platAtoms))
- this->addAtoms(platAtoms);
- }
}
}
// search libraries for overrides of common symbols
@@ -230,21 +193,8 @@ void Resolver::updateReferences() {
}
-// for dead code stripping, recursively mark atom "live"
-void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
- // if -why_live cares about this symbol, then dump chain
- if ((previous->referer != nullptr) && _platform.printWhyLive(atom.name())) {
- llvm::errs() << atom.name() << " from " << atom.file().path() << "\n";
- int depth = 1;
- for (WhyLiveBackChain *p = previous; p != nullptr;
- p = p->previous, ++depth) {
- for (int i = depth; i > 0; --i)
- llvm::errs() << " ";
- llvm::errs() << p->referer->name() << " from "
- << p->referer->file().path() << "\n";
- }
- }
-
+// for dead code stripping, recursively mark atoms "live"
+void Resolver::markLive(const Atom &atom) {
// if already marked live, then done (stop recursion)
if ( _liveAtoms.count(&atom) )
return;
@@ -253,50 +203,47 @@ void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
_liveAtoms.insert(&atom);
// mark all atoms it references as live
- WhyLiveBackChain thisChain;
- thisChain.previous = previous;
- thisChain.referer = &atom;
if ( const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
for (const Reference *ref : *defAtom) {
- this->markLive(*ref->target(), &thisChain);
+ const Atom *target = ref->target();
+ if ( target != nullptr )
+ this->markLive(*target);
}
}
}
+
// remove all atoms not actually used
void Resolver::deadStripOptimize() {
// only do this optimization with -dead_strip
- if (!_platform.deadCodeStripping())
+ if (!_options.deadCodeStripping())
return;
// clear liveness on all atoms
_liveAtoms.clear();
- // add entry point (main) to live roots
- const Atom *entry = this->entryPoint();
- if (entry != nullptr)
- _deadStripRoots.insert(entry);
-
- // add -exported_symbols_list, -init, and -u entries to live roots
- for (Platform::UndefinesIterator uit = _platform.initialUndefinesBegin();
- uit != _platform.initialUndefinesEnd(); ++uit) {
- StringRef sym = *uit;
- const Atom *symAtom = _symbolTable.findByName(sym);
+ // By default, shared libraries are built with all globals as dead strip roots
+ if ( _options.allGlobalsAreDeadStripRoots() ) {
+ for ( const Atom *atom : _atoms ) {
+ const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom);
+ if (defAtom == nullptr)
+ continue;
+ if ( defAtom->scope() == DefinedAtom::scopeGlobal )
+ _deadStripRoots.insert(defAtom);
+ }
+ }
+
+ // Or, use list of names that are dead stip roots.
+ const std::vector<StringRef> &names = _options.deadStripRootNames();
+ for ( const StringRef &name : names ) {
+ const Atom *symAtom = _symbolTable.findByName(name);
assert(symAtom->definition() != Atom::definitionUndefined);
_deadStripRoots.insert(symAtom);
}
- // add platform specific helper atoms
- std::vector<const DefinedAtom *> platRootAtoms;
- if (_platform.getImplicitDeadStripRoots(platRootAtoms))
- this->addAtoms(platRootAtoms);
-
// mark all roots as live, and recursively all atoms they reference
for ( const Atom *dsrAtom : _deadStripRoots) {
- WhyLiveBackChain rootChain;
- rootChain.previous = nullptr;
- rootChain.referer = dsrAtom;
- this->markLive(*dsrAtom, &rootChain);
+ this->markLive(*dsrAtom);
}
// now remove all non-live atoms from _atoms
@@ -304,6 +251,7 @@ void Resolver::deadStripOptimize() {
NotLive(_liveAtoms)), _atoms.end());
}
+
// error out if some undefines remain
void Resolver::checkUndefines(bool final) {
// when using LTO, undefines are checked after bitcode is optimized
@@ -313,18 +261,25 @@ void Resolver::checkUndefines(bool final) {
// build vector of remaining undefined symbols
std::vector<const Atom *> undefinedAtoms;
_symbolTable.undefines(undefinedAtoms);
- if (_platform.deadCodeStripping()) {
- // when dead code stripping we don't care if dead atoms are undefined
+ if (_options.deadCodeStripping()) {
+ // When dead code stripping, we don't care if dead atoms are undefined.
undefinedAtoms.erase(std::remove_if(
undefinedAtoms.begin(), undefinedAtoms.end(),
NotLive(_liveAtoms)), undefinedAtoms.end());
}
- // let platform make error message about missing symbols
- if (undefinedAtoms.size() != 0)
- _platform.errorWithUndefines(undefinedAtoms, _atoms);
+ // error message about missing symbols
+ if ( (undefinedAtoms.size() != 0) && _options.undefinesAreErrors() ) {
+ // FIXME: need diagonstics interface for writing error messages
+ llvm::errs() << "Undefined symbols:\n";
+ for ( const Atom *undefAtom : undefinedAtoms ) {
+ llvm::errs() << " " << undefAtom->name() << "\n";
+ }
+ llvm::report_fatal_error("symbol(s) not found");
+ }
}
+
// remove from _atoms all coaleseced away atoms
void Resolver::removeCoalescedAwayAtoms() {
_atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
@@ -348,27 +303,12 @@ void Resolver::checkDylibSymbolCollisions() {
}
}
-// get "main" atom for linkage unit
-const Atom *Resolver::entryPoint() {
- StringRef symbolName = _platform.entryPointName();
- if ( !symbolName.empty() )
- return _symbolTable.findByName(symbolName);
-
- return nullptr;
-}
-
-// give platform a chance to tweak the set of atoms
-void Resolver::tweakAtoms() {
- _platform.postResolveTweaks(_atoms);
-}
void Resolver::linkTimeOptimize() {
// FIX ME
}
void Resolver::resolve() {
- this->initializeState();
- this->addInitialUndefines();
this->buildInitialAtomList();
this->resolveUndefines();
this->updateReferences();
@@ -377,9 +317,7 @@ void Resolver::resolve() {
this->removeCoalescedAwayAtoms();
this->checkDylibSymbolCollisions();
this->linkTimeOptimize();
- this->tweakAtoms();
this->_result.addAtoms(_atoms);
- this->_result._mainAtom = this->entryPoint();
}
void Resolver::MergedFile::addAtom(const Atom& atom) {
diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp
index 96b1e51752d..e2269749062 100644
--- a/lld/lib/Core/SymbolTable.cpp
+++ b/lld/lib/Core/SymbolTable.cpp
@@ -14,7 +14,6 @@
#include "lld/Core/File.h"
#include "lld/Core/InputFiles.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
@@ -22,6 +21,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -30,8 +30,8 @@
namespace lld {
-SymbolTable::SymbolTable(Platform& plat)
- : _platform(plat) {
+SymbolTable::SymbolTable(ResolverOptions &opts)
+ : _options(opts) {
}
void SymbolTable::add(const UndefinedAtom &atom) {
@@ -171,29 +171,56 @@ void SymbolTable::addByName(const Atom & newAtom) {
useNew = false;
}
else {
+ if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
+ // FIXME: need diagonstics interface for writing warning messages
+ llvm::errs() << "lld warning: undefined symbol "
+ << existingUndef->name()
+ << " has different weakness in "
+ << existingUndef->file().path()
+ << " and in "
+ << newUndef->file().path();
+ }
useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
- // give platform a change to override which to use
- _platform.undefineCanBeNullMismatch(*existingUndef,
- *newUndef, useNew);
}
}
break;
case NCR_DupShLib: {
- const SharedLibraryAtom* existingShLib =
+ const SharedLibraryAtom* curShLib =
dyn_cast<SharedLibraryAtom>(existing);
const SharedLibraryAtom* newShLib =
dyn_cast<SharedLibraryAtom>(&newAtom);
- assert(existingShLib != nullptr);
+ assert(curShLib != nullptr);
assert(newShLib != nullptr);
- if ( (existingShLib->canBeNullAtRuntime()
- == newShLib->canBeNullAtRuntime()) &&
- existingShLib->loadName().equals(newShLib->loadName()) ) {
+ bool sameNullness = (curShLib->canBeNullAtRuntime()
+ == newShLib->canBeNullAtRuntime());
+ bool sameName = curShLib->loadName().equals(newShLib->loadName());
+ if ( !sameName ) {
useNew = false;
+ if ( _options.warnIfCoalesableAtomsHaveDifferentLoadName() ) {
+ // FIXME: need diagonstics interface for writing warning messages
+ llvm::errs() << "lld warning: shared library symbol "
+ << curShLib->name()
+ << " has different load path in "
+ << curShLib->file().path()
+ << " and in "
+ << newShLib->file().path();
+ }
+ }
+ else if ( ! sameNullness ) {
+ useNew = false;
+ if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
+ // FIXME: need diagonstics interface for writing warning messages
+ llvm::errs() << "lld warning: shared library symbol "
+ << curShLib->name()
+ << " has different weakness in "
+ << curShLib->file().path()
+ << " and in "
+ << newShLib->file().path();
+ }
}
else {
- useNew = false; // use existing shared library by default
- // give platform a change to override which to use
- _platform.sharedLibrarylMismatch(*existingShLib, *newShLib, useNew);
+ // Both shlib atoms are identical and can be coalesced.
+ useNew = false;
}
}
break;
diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/Core/YamlKeyValues.cpp
index 548cafa261f..abf6f16f8c6 100644
--- a/lld/lib/Core/YamlKeyValues.cpp
+++ b/lld/lib/Core/YamlKeyValues.cpp
@@ -138,6 +138,7 @@ static const ContentTypeMapping typeMappings[] = {
{ "unknown", DefinedAtom::typeUnknown },
{ "code", DefinedAtom::typeCode },
{ "stub", DefinedAtom::typeStub },
+ { "stub-helper", DefinedAtom::typeStubHelper },
{ "resolver", DefinedAtom::typeResolver },
{ "constant", DefinedAtom::typeConstant },
{ "c-string", DefinedAtom::typeCString },
@@ -151,6 +152,7 @@ static const ContentTypeMapping typeMappings[] = {
{ "zero-fill", DefinedAtom::typeZeroFill },
{ "cf-string", DefinedAtom::typeCFString },
{ "got", DefinedAtom::typeGOT },
+ { "lazy-pointer", DefinedAtom::typeLazyPointer },
{ "initializer-ptr",DefinedAtom::typeInitializerPtr },
{ "terminator-ptr", DefinedAtom::typeTerminatorPtr },
{ "c-string-ptr", DefinedAtom::typeCStringPtr },
diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp
index c5f45c9025f..e056eb898c9 100644
--- a/lld/lib/Core/YamlWriter.cpp
+++ b/lld/lib/Core/YamlWriter.cpp
@@ -56,11 +56,12 @@ public:
// Find references to unnamed atoms and create ref-names for them.
for (const Reference *ref : *atom) {
// create refname for any unnamed reference target
- if ( ref->target()->name().empty() ) {
+ const Atom *target = ref->target();
+ if ( (target != nullptr) && target->name().empty() ) {
std::string Storage;
llvm::raw_string_ostream Buffer(Storage);
Buffer << llvm::format("L%03d", _unnamedCounter++);
- _refNames[ref->target()] = Buffer.str();
+ _refNames[target] = Buffer.str();
}
}
}
diff --git a/lld/lib/Platforms/Darwin/DarwinPlatform.cpp b/lld/lib/Platforms/Darwin/DarwinPlatform.cpp
index d3fcd681efd..3fdc039095a 100644
--- a/lld/lib/Platforms/Darwin/DarwinPlatform.cpp
+++ b/lld/lib/Platforms/Darwin/DarwinPlatform.cpp
@@ -10,12 +10,14 @@
#include "DarwinPlatform.h"
#include "MachOFormat.hpp"
#include "StubAtoms.hpp"
+#include "ExecutableAtoms.hpp"
#include "DarwinReferenceKinds.h"
#include "ExecutableWriter.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
+#include "lld/Core/InputFiles.h"
#include "llvm/Support/ErrorHandling.h"
@@ -29,110 +31,14 @@ Platform *createDarwinPlatform() {
namespace darwin {
DarwinPlatform::DarwinPlatform()
- : _helperCommonAtom(nullptr) {
+ : _helperCommonAtom(nullptr), _cRuntimeFile(nullptr) {
}
-void DarwinPlatform::initialize() {
+void DarwinPlatform::addFiles(InputFiles &inputFiles) {
+ _cRuntimeFile = new CRuntimeFile();
+ inputFiles.prependFile(*_cRuntimeFile);
}
-void DarwinPlatform::fileAdded(const File &file) {
-}
-
-
-void DarwinPlatform::atomAdded(const Atom &file) {
-}
-
-
-void DarwinPlatform::adjustScope(const DefinedAtom &atom) {
-}
-
-
-bool DarwinPlatform::getAliasAtoms(const Atom &atom,
- std::vector<const DefinedAtom *>&) {
- return false;
-}
-
-
-bool DarwinPlatform::getPlatformAtoms(StringRef undefined,
- std::vector<const DefinedAtom *>&) {
- return false;
-}
-
-
-bool DarwinPlatform::deadCodeStripping() {
- return false;
-}
-
-
-bool DarwinPlatform::isDeadStripRoot(const Atom &atom) {
- return false;
-}
-
-
-bool DarwinPlatform::getImplicitDeadStripRoots(std::vector<const DefinedAtom *>&) {
- return false;
-}
-
-
-StringRef DarwinPlatform::entryPointName() {
- return StringRef("_main");
-}
-
-
-Platform::UndefinesIterator DarwinPlatform::initialUndefinesBegin() const {
- return nullptr;
-}
-
-Platform::UndefinesIterator DarwinPlatform::initialUndefinesEnd() const {
- return nullptr;
-}
-
-
-bool DarwinPlatform::searchArchivesToOverrideTentativeDefinitions() {
- return false;
-}
-
-bool DarwinPlatform::searchSharedLibrariesToOverrideTentativeDefinitions() {
- return false;
-}
-
-
-bool DarwinPlatform::allowUndefinedSymbol(StringRef name) {
- return false;
-}
-
-bool DarwinPlatform::printWhyLive(StringRef name) {
- return false;
-}
-
-
-const Atom& DarwinPlatform::handleMultipleDefinitions(const Atom& def1,
- const Atom& def2) {
- llvm::report_fatal_error("multiple definitions");
-}
-
-
-void DarwinPlatform::errorWithUndefines(const std::vector<const Atom *>& undefs,
- const std::vector<const Atom *>& all) {
-}
-
-
-void DarwinPlatform::undefineCanBeNullMismatch(const UndefinedAtom& undef1,
- const UndefinedAtom& undef2,
- bool& useUndef2) {
-}
-
-
-void DarwinPlatform::sharedLibrarylMismatch(const SharedLibraryAtom& shLib1,
- const SharedLibraryAtom& shLib2,
- bool& useShlib2) {
-}
-
-
-void DarwinPlatform::postResolveTweaks(std::vector<const Atom *>& all) {
-}
-
-
Reference::Kind DarwinPlatform::kindFromString(StringRef kindName) {
return ReferenceKind::fromString(kindName);
}
@@ -259,6 +165,16 @@ void DarwinPlatform::initializeMachHeader(const lld::File& file,
mh.reserved = 0;
}
+const Atom *DarwinPlatform::mainAtom() {
+ assert(_cRuntimeFile != nullptr);
+ const Atom *result = _cRuntimeFile->mainAtom();
+ assert(result != nullptr);
+ if ( result->definition() == Atom::definitionUndefined )
+ llvm::report_fatal_error("_main not found");
+ return _cRuntimeFile->mainAtom();
+}
+
+
} // namespace darwin
} // namespace lld
diff --git a/lld/lib/Platforms/Darwin/DarwinPlatform.h b/lld/lib/Platforms/Darwin/DarwinPlatform.h
index f7608b507da..c05fb9c2bbb 100644
--- a/lld/lib/Platforms/Darwin/DarwinPlatform.h
+++ b/lld/lib/Platforms/Darwin/DarwinPlatform.h
@@ -23,35 +23,7 @@ public:
/// @name Platform methods
/// @{
- virtual void initialize();
- virtual void fileAdded(const File &file);
- virtual void atomAdded(const Atom &file);
- virtual void adjustScope(const DefinedAtom &atom);
- virtual bool getAliasAtoms(const Atom &atom,
- std::vector<const DefinedAtom *>&);
- virtual bool getPlatformAtoms(llvm::StringRef undefined,
- std::vector<const DefinedAtom *>&);
- virtual bool deadCodeStripping();
- virtual bool isDeadStripRoot(const Atom &atom);
- virtual bool getImplicitDeadStripRoots(std::vector<const DefinedAtom *>&);
- virtual llvm::StringRef entryPointName();
- virtual UndefinesIterator initialUndefinesBegin() const;
- virtual UndefinesIterator initialUndefinesEnd() const;
- virtual bool searchArchivesToOverrideTentativeDefinitions();
- virtual bool searchSharedLibrariesToOverrideTentativeDefinitions();
- virtual bool allowUndefinedSymbol(llvm::StringRef name);
- virtual bool printWhyLive(llvm::StringRef name);
- virtual const Atom& handleMultipleDefinitions(const Atom& def1,
- const Atom& def2);
- virtual void errorWithUndefines(const std::vector<const Atom *>& undefs,
- const std::vector<const Atom *>& all);
- virtual void undefineCanBeNullMismatch(const UndefinedAtom& undef1,
- const UndefinedAtom& undef2,
- bool& useUndef2);
- virtual void sharedLibrarylMismatch(const SharedLibraryAtom& shLib1,
- const SharedLibraryAtom& shLib2,
- bool& useShlib2);
- virtual void postResolveTweaks(std::vector<const Atom *>& all);
+ virtual void addFiles(InputFiles&);
virtual Reference::Kind kindFromString(llvm::StringRef);
virtual llvm::StringRef kindToString(Reference::Kind);
virtual bool noTextRelocs();
@@ -69,6 +41,7 @@ public:
/// @{
uint64_t pageZeroSize();
void initializeMachHeader(const lld::File& file, class mach_header& mh);
+ const Atom *mainAtom();
/// @}
private:
@@ -79,6 +52,7 @@ private:
const DefinedAtom* _helperCommonAtom;
const DefinedAtom* _helperCacheAtom;
const DefinedAtom* _helperBinderAtom;
+ class CRuntimeFile *_cRuntimeFile;
};
} // namespace darwin
diff --git a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp b/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
index d1d56b2860c..3cc676c6884 100644
--- a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
+++ b/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
@@ -32,6 +32,7 @@ enum {
static const Mapping sKindMappings[] = {
+ { "none", ReferenceKind::none, flagsNone },
{ "call32", ReferenceKind::call32, flagsIsCallSite | flags32RipRel },
{ "pcrel32", ReferenceKind::pcRel32, flags32RipRel },
{ "gotLoad32", ReferenceKind::gotLoad32, flagsisGOTLoad | flags32RipRel },
diff --git a/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp b/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp
new file mode 100644
index 00000000000..31bd181ccb3
--- /dev/null
+++ b/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp
@@ -0,0 +1,84 @@
+//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
+#define LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
+
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+#include "DarwinReferenceKinds.h"
+#include "SimpleAtoms.hpp"
+
+namespace lld {
+namespace darwin {
+
+
+//
+// EntryPointReferenceAtom is used to:
+// 1) Require "_main" is defined.
+// 2) Give Darwin Platform a pointer to the atom named "_main"
+//
+class EntryPointReferenceAtom : public SimpleDefinedAtom {
+public:
+ EntryPointReferenceAtom(const File &file)
+ : SimpleDefinedAtom(file)
+ , _mainUndefAtom(file, "_main") {
+ this->addReference(ReferenceKind::none, 0, &_mainUndefAtom, 0);
+ }
+
+ virtual ContentType contentType() const {
+ return DefinedAtom::typeCode;
+ }
+
+ virtual uint64_t size() const {
+ return 0;
+ }
+
+ virtual ContentPermissions permissions() const {
+ return DefinedAtom::permR_X;
+ }
+
+ virtual ArrayRef<uint8_t> rawContent() const {
+ return ArrayRef<uint8_t>();
+ }
+private:
+ friend class CRuntimeFile;
+ SimpleUndefinedAtom _mainUndefAtom;
+};
+
+
+class CRuntimeFile : public SimpleFile {
+public:
+ CRuntimeFile()
+ : SimpleFile("C runtime")
+ , _atom(*this) {
+ this->addAtom(_atom);
+ this->addAtom(_atom._mainUndefAtom);
+ }
+
+ const Atom *mainAtom() {
+ const Reference *ref = *(_atom.begin());
+ return ref->target();
+ }
+
+private:
+ EntryPointReferenceAtom _atom;
+};
+
+
+
+} // namespace darwin
+} // namespace lld
+
+
+#endif // LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
diff --git a/lld/lib/Platforms/Darwin/ExecutableWriter.cpp b/lld/lib/Platforms/Darwin/ExecutableWriter.cpp
index e9f05e0e84b..3ebf3517748 100644
--- a/lld/lib/Platforms/Darwin/ExecutableWriter.cpp
+++ b/lld/lib/Platforms/Darwin/ExecutableWriter.cpp
@@ -554,7 +554,10 @@ void SectionChunk::write(raw_ostream &out) {
}
// Copy raw content of atom.
ArrayRef<uint8_t> content = atomInfo.atom->rawContent();
- buffer.resize(content.size());
+ uint64_t contentSize = content.size();
+ buffer.resize(contentSize);
+ if ( contentSize == 0 )
+ continue;
::memcpy(buffer.data(), content.data(), content.size());
for (const Reference *ref : *atomInfo.atom) {
uint32_t offset = ref->offsetInAtom();
@@ -808,7 +811,7 @@ void LoadCommandsChunk::updateLoadCommandContent(const lld::File &file) {
// Update entry point
if ( _entryPointLoadCommand != nullptr ) {
- const Atom *mainAtom = file.entryPoint();
+ const Atom *mainAtom = _platform.mainAtom();
assert(mainAtom != nullptr);
uint32_t entryOffset = _writer.addressOfAtom(mainAtom) - _mh.address();
_entryPointLoadCommand->entryoff = entryOffset;
diff --git a/lld/lib/Platforms/Darwin/SimpleAtoms.hpp b/lld/lib/Platforms/Darwin/SimpleAtoms.hpp
new file mode 100644
index 00000000000..f9c7aa0130d
--- /dev/null
+++ b/lld/lib/Platforms/Darwin/SimpleAtoms.hpp
@@ -0,0 +1,247 @@
+//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
+#define LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
+
+#include <vector>
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+namespace lld {
+namespace darwin {
+
+
+//
+// Simple File
+//
+class SimpleFile : public File {
+public:
+ SimpleFile(StringRef path)
+ : File(path) {
+ }
+
+ virtual void addAtom(const Atom &atom) {
+ if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
+ _definedAtoms._atoms.push_back(defAtom);
+ }
+ else if (const UndefinedAtom* undefAtom = dyn_cast<UndefinedAtom>(&atom)) {
+ _undefinedAtoms._atoms.push_back(undefAtom);
+ }
+ else if (const SharedLibraryAtom* slAtom =
+ dyn_cast<SharedLibraryAtom>(&atom)) {
+ _sharedLibraryAtoms._atoms.push_back(slAtom);
+ }
+ else if (const AbsoluteAtom* abAtom = dyn_cast<AbsoluteAtom>(&atom)) {
+ _absoluteAtoms._atoms.push_back(abAtom);
+ }
+ else {
+ assert(0 && "atom has unknown definition kind");
+ }
+ }
+
+ 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;
+};
+
+
+
+//
+// Simple Reference
+//
+class SimpleReference : public Reference {
+public:
+ SimpleReference(Reference::Kind k, uint64_t off,
+ const Atom *t, Reference::Addend a)
+ : _target(t), _offsetInAtom(off), _addend(a), _kind(k) { }
+
+ virtual uint64_t offsetInAtom() const {
+ return _offsetInAtom;
+ }
+
+ virtual Kind kind() const {
+ return _kind;
+ }
+
+ virtual void setKind(Kind k) {
+ _kind = k;
+ }
+
+ virtual const Atom* target() const {
+ return _target;
+ }
+
+ virtual Addend addend() const {
+ return _addend;
+ }
+
+ virtual void setAddend(Addend a) {
+ _addend = a;
+ }
+
+ virtual void setTarget(const Atom* newAtom) {
+ _target = newAtom;
+ }
+private:
+ const Atom* _target;
+ uint64_t _offsetInAtom;
+ Addend _addend;
+ Kind _kind;
+};
+
+
+//
+// Generic Atom base class
+//
+class SimpleDefinedAtom : public DefinedAtom {
+public:
+ SimpleDefinedAtom(const File &f) : _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 Scope scope() const {
+ return DefinedAtom::scopeLinkageUnit;
+ }
+
+ virtual Interposable interposable() const {
+ return DefinedAtom::interposeNo;
+ }
+
+ virtual Merge merge() const {
+ return DefinedAtom::mergeNo;
+ }
+
+ virtual Alignment alignment() const {
+ return Alignment(0,0);
+ }
+
+ virtual SectionChoice sectionChoice() const {
+ return DefinedAtom::sectionBasedOnContent;
+ }
+
+ virtual StringRef customSectionName() const {
+ return StringRef();
+ }
+ virtual DeadStripKind deadStrip() const {
+ return DefinedAtom::deadStripNormal;
+ }
+
+ virtual bool isThumb() const {
+ return false;
+ }
+
+ virtual bool isAlias() const {
+ return false;
+ }
+
+ virtual DefinedAtom::reference_iterator begin() const {
+ uintptr_t index = 0;
+ const void* it = reinterpret_cast<const void*>(index);
+ return reference_iterator(*this, it);
+ }
+
+ virtual DefinedAtom::reference_iterator end() const {
+ uintptr_t index = _references.size();
+ const void* it = reinterpret_cast<const void*>(index);
+ return reference_iterator(*this, it);
+ }
+
+ virtual const Reference* derefIterator(const void* it) const {
+ uintptr_t index = reinterpret_cast<uintptr_t>(it);
+ assert(index < _references.size());
+ return &_references[index];
+ }
+
+ virtual void incrementIterator(const void*& it) const {
+ uintptr_t index = reinterpret_cast<uintptr_t>(it);
+ ++index;
+ it = reinterpret_cast<const void*>(index);
+ }
+
+ void addReference(Reference::Kind kind, uint64_t offset, const Atom *target,
+ Reference::Addend addend) {
+ _references.push_back(SimpleReference(kind, offset, target, addend));
+ }
+
+private:
+ const File& _file;
+ uint32_t _ordinal;
+ std::vector<SimpleReference> _references;
+};
+
+
+
+//
+// Generic UndefinedAtom base class
+//
+class SimpleUndefinedAtom : public UndefinedAtom {
+public:
+ SimpleUndefinedAtom(const File &f, StringRef name)
+ : _file(f), _name(name) {
+ }
+
+ /// file - returns the File that produced/owns this Atom
+ virtual const class File& file() const {
+ return _file;
+ }
+
+ /// name - The name of the atom. For a function atom, it is the (mangled)
+ /// name of the function.
+ virtual StringRef name() const {
+ return _name;
+ }
+
+ virtual CanBeNull canBeNull() const {
+ return UndefinedAtom::canBeNullNever;
+ }
+
+private:
+ const File& _file;
+ StringRef _name;
+};
+
+
+
+} // namespace darwin
+} // namespace lld
+
+
+#endif // LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
diff --git a/lld/lib/Platforms/Darwin/StubAtoms.hpp b/lld/lib/Platforms/Darwin/StubAtoms.hpp
index ed30f936663..1023d42010e 100644
--- a/lld/lib/Platforms/Darwin/StubAtoms.hpp
+++ b/lld/lib/Platforms/Darwin/StubAtoms.hpp
@@ -10,8 +10,6 @@
#ifndef LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
#define LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
-#include <vector>
-
#include "llvm/ADT/ArrayRef.h"
#include "lld/Core/DefinedAtom.h"
@@ -20,156 +18,19 @@
#include "lld/Core/Reference.h"
#include "DarwinReferenceKinds.h"
+#include "SimpleAtoms.hpp"
namespace lld {
namespace darwin {
//
-// Generic Reference
-//
-class GenericReference : public Reference {
-public:
- GenericReference(Reference::Kind k, uint64_t off,
- const Atom *t, Reference::Addend a)
- : _target(t), _offsetInAtom(off), _addend(a), _kind(k) { }
-
- virtual uint64_t offsetInAtom() const {
- return _offsetInAtom;
- }
-
- virtual Kind kind() const {
- return _kind;
- }
-
- virtual void setKind(Kind k) {
- _kind = k;
- }
-
- virtual const Atom* target() const {
- return _target;
- }
-
- virtual Addend addend() const {
- return _addend;
- }
-
- virtual void setAddend(Addend a) {
- _addend = a;
- }
-
- virtual void setTarget(const Atom* newAtom) {
- _target = newAtom;
- }
-private:
- const Atom* _target;
- uint64_t _offsetInAtom;
- Addend _addend;
- Kind _kind;
-};
-
-
-//
-// Generic Atom base class
-//
-class BaseAtom : public DefinedAtom {
-public:
- BaseAtom(const File &f) : _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 Scope scope() const {
- return DefinedAtom::scopeLinkageUnit;
- }
-
- virtual Interposable interposable() const {
- return DefinedAtom::interposeNo;
- }
-
- virtual Merge merge() const {
- return DefinedAtom::mergeNo;
- }
-
- virtual Alignment alignment() const {
- return Alignment(0,0);
- }
-
- virtual SectionChoice sectionChoice() const {
- return DefinedAtom::sectionBasedOnContent;
- }
-
- virtual StringRef customSectionName() const {
- return StringRef();
- }
- virtual DeadStripKind deadStrip() const {
- return DefinedAtom::deadStripNormal;
- }
-
- virtual bool isThumb() const {
- return false;
- }
-
- virtual bool isAlias() const {
- return false;
- }
-
- virtual DefinedAtom::reference_iterator begin() const {
- uintptr_t index = 0;
- const void* it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
- }
-
- virtual DefinedAtom::reference_iterator end() const {
- uintptr_t index = _references.size();
- const void* it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
- }
-
- virtual const Reference* derefIterator(const void* it) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(it);
- assert(index < _references.size());
- return &_references[index];
- }
-
- virtual void incrementIterator(const void*& it) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(it);
- ++index;
- it = reinterpret_cast<const void*>(index);
- }
-
- void addReference(Reference::Kind kind, uint64_t offset, const Atom *target,
- Reference::Addend addend) {
- _references.push_back(GenericReference(kind, offset, target, addend));
- }
-
-private:
- const File& _file;
- uint32_t _ordinal;
- std::vector<GenericReference> _references;
-};
-
-
-
-//
// X86_64 Stub Atom created by the stubs pass.
//
-class X86_64StubAtom : public BaseAtom {
+class X86_64StubAtom : public SimpleDefinedAtom {
public:
X86_64StubAtom(const File &file, const Atom &lazyPointer)
- : BaseAtom(file) {
+ : SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::pcRel32, 2, &lazyPointer, 0);
}
@@ -198,11 +59,11 @@ public:
//
// X86_64 Stub Helper Common Atom created by the stubs pass.
//
-class X86_64StubHelperCommonAtom : public BaseAtom {
+class X86_64StubHelperCommonAtom : public SimpleDefinedAtom {
public:
X86_64StubHelperCommonAtom(const File &file, const Atom &cache,
const Atom &binder)
- : BaseAtom(file) {
+ : SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::pcRel32, 3, &cache, 0);
this->addReference(ReferenceKind::pcRel32, 11, &binder, 0);
}
@@ -236,10 +97,10 @@ public:
//
// X86_64 Stub Helper Atom created by the stubs pass.
//
-class X86_64StubHelperAtom : public BaseAtom {
+class X86_64StubHelperAtom : public SimpleDefinedAtom {
public:
X86_64StubHelperAtom(const File &file, const Atom &helperCommon)
- : BaseAtom(file) {
+ : SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::lazyImm, 1, nullptr, 0);
this->addReference(ReferenceKind::pcRel32, 6, &helperCommon, 0);
}
@@ -270,11 +131,11 @@ public:
//
// X86_64 Lazy Pointer Atom created by the stubs pass.
//
-class X86_64LazyPointerAtom : public BaseAtom {
+class X86_64LazyPointerAtom : public SimpleDefinedAtom {
public:
X86_64LazyPointerAtom(const File &file, const Atom &helper,
const Atom &shlib)
- : BaseAtom(file) {
+ : SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::pointer64, 0, &helper, 0);
this->addReference(ReferenceKind::lazyTarget, 0, &shlib, 0);
}
@@ -303,14 +164,14 @@ public:
//
// X86_64 NonLazy (GOT) Pointer Atom created by the stubs pass.
//
-class X86_64NonLazyPointerAtom : public BaseAtom {
+class X86_64NonLazyPointerAtom : public SimpleDefinedAtom {
public:
X86_64NonLazyPointerAtom(const File &file)
- : BaseAtom(file) {
+ : SimpleDefinedAtom(file) {
}
X86_64NonLazyPointerAtom(const File &file, const Atom &shlib)
- : BaseAtom(file) {
+ : SimpleDefinedAtom(file) {
this->addReference(ReferenceKind::pointer64, 0, &shlib, 0);
}
OpenPOWER on IntegriCloud