blob: 0cf5838bb1fd347860608b5fc376f496854828d5 [file] [log] [blame]
Michael J. Spencer773a8fb2011-12-18 08:27:59 +00001//===- Core/Resolver.cpp - Resolves Atom References -----------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Nick Kledzikb334be12012-04-07 01:31:00 +000010#include "lld/Core/LLVM.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000011#include "lld/Core/Resolver.h"
12#include "lld/Core/Atom.h"
13#include "lld/Core/File.h"
14#include "lld/Core/InputFiles.h"
Michael J. Spencere6203a52012-04-03 18:39:40 +000015#include "lld/Core/LLVM.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000016#include "lld/Core/Platform.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000017#include "lld/Core/SymbolTable.h"
18#include "lld/Core/UndefinedAtom.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000019
20#include "llvm/Support/raw_ostream.h"
21
22#include <algorithm>
23#include <cassert>
24#include <vector>
25
26namespace lld {
27
Michael J. Spencer765792d2012-04-03 18:40:27 +000028/// This is used as a filter function to std::remove_if to dead strip atoms.
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000029class NotLive {
30public:
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000031 NotLive(const llvm::DenseSet<const Atom*>& la) : _liveAtoms(la) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +000032
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000033 bool operator()(const Atom *atom) const {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000034 // don't remove if live
35 if ( _liveAtoms.count(atom) )
36 return false;
Nick Kledzik23384e82012-02-07 02:59:54 +000037 // don't remove if marked never-dead-strip
Michael J. Spencere6203a52012-04-03 18:39:40 +000038 if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom)) {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000039 if ( defAtom->deadStrip() == DefinedAtom::deadStripNever )
40 return false;
41 }
42 // do remove this atom
43 return true;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000044 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000045
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000046private:
47 const llvm::DenseSet<const Atom*> _liveAtoms;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000048};
49
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000050
Michael J. Spencer765792d2012-04-03 18:40:27 +000051/// This is used as a filter function to std::remove_if to coalesced atoms.
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000052class AtomCoalescedAway {
53public:
54 AtomCoalescedAway(SymbolTable &sym) : _symbolTable(sym) {}
55
56 bool operator()(const Atom *atom) const {
57 const Atom *rep = _symbolTable.replacement(atom);
58 return rep != atom;
59 }
60
61private:
62 SymbolTable &_symbolTable;
63};
64
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000065
66
67
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000068void Resolver::initializeState() {
69 _platform.initialize();
70}
71
72// add initial undefines from -u option
73void Resolver::addInitialUndefines() {
74
75}
76
77// add all atoms from all initial .o files
78void Resolver::buildInitialAtomList() {
79 // each input files contributes initial atoms
80 _atoms.reserve(1024);
81 _inputFiles.forEachInitialAtom(*this);
82
83 _completedInitialObjectFiles = true;
84}
85
86
87// called before the first atom in any file is added with doAtom()
88void Resolver::doFile(const File &file) {
89 // notify platform
90 _platform.fileAdded(file);
91}
92
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000093
94void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
95 // add to list of known atoms
96 _atoms.push_back(&atom);
Michael J. Spencer765792d2012-04-03 18:40:27 +000097
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000098 // tell symbol table
99 _symbolTable.add(atom);
100}
101
102
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000103// called on each atom when a file is added
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000104void Resolver::doDefinedAtom(const DefinedAtom &atom) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000105 // notify platform
106 _platform.atomAdded(atom);
107
108 // add to list of known atoms
109 _atoms.push_back(&atom);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000110
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000111 // adjust scope (e.g. force some globals to be hidden)
112 _platform.adjustScope(atom);
113
114 // non-static atoms need extra handling
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000115 if (atom.scope() != DefinedAtom::scopeTranslationUnit) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000116 // tell symbol table about non-static atoms
117 _symbolTable.add(atom);
118
119 // platform can add aliases for any symbol
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000120 std::vector<const DefinedAtom *> aliases;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000121 if (_platform.getAliasAtoms(atom, aliases))
122 this->addAtoms(aliases);
123 }
124
125 if (_platform.deadCodeStripping()) {
126 // add to set of dead-strip-roots, all symbols that
127 // the compiler marks as don't strip
128 if (!atom.deadStrip())
129 _deadStripRoots.insert(&atom);
130
131 // add to set of dead-strip-roots, all symbols that
132 // the platform decided must remain
133 if (_platform.isDeadStripRoot(atom))
134 _deadStripRoots.insert(&atom);
135 }
136}
137
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000138void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
139 // add to list of known atoms
140 _atoms.push_back(&atom);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000141
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000142 // tell symbol table
143 _symbolTable.add(atom);
144}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000145
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000146void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) {
147 // add to list of known atoms
148 _atoms.push_back(&atom);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000149
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000150 // tell symbol table
151 _symbolTable.add(atom);
152}
153
154
Michael J. Spencer765792d2012-04-03 18:40:27 +0000155
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000156// utility to add a vector of atoms
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000157void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
158 for (std::vector<const DefinedAtom *>::const_iterator it = newAtoms.begin();
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000159 it != newAtoms.end(); ++it) {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000160 this->doDefinedAtom(**it);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000161 }
162}
163
164// ask symbol table if any definitionUndefined atoms still exist
165// if so, keep searching libraries until no more atoms being added
166void Resolver::resolveUndefines() {
167 const bool searchArchives =
168 _platform.searchArchivesToOverrideTentativeDefinitions();
169 const bool searchDylibs =
170 _platform.searchSharedLibrariesToOverrideTentativeDefinitions();
171
172 // keep looping until no more undefines were added in last loop
173 unsigned int undefineGenCount = 0xFFFFFFFF;
174 while (undefineGenCount != _symbolTable.size()) {
175 undefineGenCount = _symbolTable.size();
176 std::vector<const Atom *> undefines;
177 _symbolTable.undefines(undefines);
Nick Kledzik062a98c2012-04-08 23:52:13 +0000178 for ( const Atom *undefAtom : undefines ) {
179 StringRef undefName = undefAtom->name();
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000180 // load for previous undefine may also have loaded this undefine
181 if (!_symbolTable.isDefined(undefName)) {
182 _inputFiles.searchLibraries(undefName, true, true, false, *this);
183
184 // give platform a chance to instantiate platform
185 // specific atoms (e.g. section boundary)
186 if (!_symbolTable.isDefined(undefName)) {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000187 std::vector<const DefinedAtom *> platAtoms;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000188 if (_platform.getPlatformAtoms(undefName, platAtoms))
189 this->addAtoms(platAtoms);
190 }
191 }
192 }
193 // search libraries for overrides of common symbols
194 if (searchArchives || searchDylibs) {
195 std::vector<const Atom *> tents;
Nick Kledzik062a98c2012-04-08 23:52:13 +0000196 for ( const Atom *tent : tents ) {
197 if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(tent)) {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000198 if ( defAtom->merge() == DefinedAtom::mergeAsTentative )
199 tents.push_back(defAtom);
200 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000201 }
Nick Kledzik062a98c2012-04-08 23:52:13 +0000202 for ( const Atom *tent : tents ) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000203 // load for previous tentative may also have loaded
204 // this tentative, so check again
Nick Kledzik062a98c2012-04-08 23:52:13 +0000205 StringRef tentName = tent->name();
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000206 const Atom *curAtom = _symbolTable.findByName(tentName);
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000207 assert(curAtom != nullptr);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000208 if (const DefinedAtom* curDefAtom = dyn_cast<DefinedAtom>(curAtom)) {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000209 if (curDefAtom->merge() == DefinedAtom::mergeAsTentative )
Michael J. Spencer765792d2012-04-03 18:40:27 +0000210 _inputFiles.searchLibraries(tentName, searchDylibs,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000211 true, true, *this);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000212 }
213 }
214 }
215 }
216}
217
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000218
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000219// switch all references to undefined or coalesced away atoms
220// to the new defined atom
221void Resolver::updateReferences() {
Nick Kledzik062a98c2012-04-08 23:52:13 +0000222 for(const Atom *atom : _atoms) {
223 if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom)) {
224 for (const Reference *ref : *defAtom) {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000225 const Atom* newTarget = _symbolTable.replacement(ref->target());
226 (const_cast<Reference*>(ref))->setTarget(newTarget);
227 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000228 }
229 }
230}
231
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000232
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000233// for dead code stripping, recursively mark atom "live"
234void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
235 // if -why_live cares about this symbol, then dump chain
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000236 if ((previous->referer != nullptr) && _platform.printWhyLive(atom.name())) {
Nick Kledzikf46669c2011-12-21 23:29:36 +0000237 llvm::errs() << atom.name() << " from " << atom.file().path() << "\n";
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000238 int depth = 1;
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000239 for (WhyLiveBackChain *p = previous; p != nullptr;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000240 p = p->previous, ++depth) {
241 for (int i = depth; i > 0; --i)
242 llvm::errs() << " ";
243 llvm::errs() << p->referer->name() << " from "
Nick Kledzikf46669c2011-12-21 23:29:36 +0000244 << p->referer->file().path() << "\n";
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000245 }
246 }
247
248 // if already marked live, then done (stop recursion)
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000249 if ( _liveAtoms.count(&atom) )
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000250 return;
251
252 // mark this atom is live
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000253 _liveAtoms.insert(&atom);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000254
255 // mark all atoms it references as live
256 WhyLiveBackChain thisChain;
257 thisChain.previous = previous;
258 thisChain.referer = &atom;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000259 if ( const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
Nick Kledzik062a98c2012-04-08 23:52:13 +0000260 for (const Reference *ref : *defAtom) {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000261 this->markLive(*ref->target(), &thisChain);
262 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000263 }
264}
265
266// remove all atoms not actually used
267void Resolver::deadStripOptimize() {
268 // only do this optimization with -dead_strip
269 if (!_platform.deadCodeStripping())
270 return;
271
272 // clear liveness on all atoms
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000273 _liveAtoms.clear();
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000274
275 // add entry point (main) to live roots
276 const Atom *entry = this->entryPoint();
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000277 if (entry != nullptr)
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000278 _deadStripRoots.insert(entry);
279
280 // add -exported_symbols_list, -init, and -u entries to live roots
281 for (Platform::UndefinesIterator uit = _platform.initialUndefinesBegin();
282 uit != _platform.initialUndefinesEnd(); ++uit) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000283 StringRef sym = *uit;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000284 const Atom *symAtom = _symbolTable.findByName(sym);
285 assert(symAtom->definition() != Atom::definitionUndefined);
286 _deadStripRoots.insert(symAtom);
287 }
288
289 // add platform specific helper atoms
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000290 std::vector<const DefinedAtom *> platRootAtoms;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000291 if (_platform.getImplicitDeadStripRoots(platRootAtoms))
292 this->addAtoms(platRootAtoms);
293
294 // mark all roots as live, and recursively all atoms they reference
Nick Kledzik062a98c2012-04-08 23:52:13 +0000295 for ( const Atom *dsrAtom : _deadStripRoots) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000296 WhyLiveBackChain rootChain;
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000297 rootChain.previous = nullptr;
Nick Kledzik062a98c2012-04-08 23:52:13 +0000298 rootChain.referer = dsrAtom;
299 this->markLive(*dsrAtom, &rootChain);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000300 }
301
302 // now remove all non-live atoms from _atoms
303 _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000304 NotLive(_liveAtoms)), _atoms.end());
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000305}
306
307// error out if some undefines remain
308void Resolver::checkUndefines(bool final) {
309 // when using LTO, undefines are checked after bitcode is optimized
310 if (_haveLLVMObjs && !final)
311 return;
312
313 // build vector of remaining undefined symbols
314 std::vector<const Atom *> undefinedAtoms;
315 _symbolTable.undefines(undefinedAtoms);
316 if (_platform.deadCodeStripping()) {
317 // when dead code stripping we don't care if dead atoms are undefined
318 undefinedAtoms.erase(std::remove_if(
319 undefinedAtoms.begin(), undefinedAtoms.end(),
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000320 NotLive(_liveAtoms)), undefinedAtoms.end());
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000321 }
322
323 // let platform make error message about missing symbols
324 if (undefinedAtoms.size() != 0)
325 _platform.errorWithUndefines(undefinedAtoms, _atoms);
326}
327
328// remove from _atoms all coaleseced away atoms
329void Resolver::removeCoalescedAwayAtoms() {
330 _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
331 AtomCoalescedAway(_symbolTable)), _atoms.end());
332}
333
334// check for interactions between symbols defined in this linkage unit
335// and same symbol name in linked dynamic shared libraries
336void Resolver::checkDylibSymbolCollisions() {
Nick Kledzik062a98c2012-04-08 23:52:13 +0000337 for ( const Atom *atom : _atoms ) {
338 const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom);
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000339 if (defAtom == nullptr)
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000340 continue;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000341 if ( defAtom->merge() != DefinedAtom::mergeAsTentative )
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000342 continue;
343 assert(defAtom->scope() != DefinedAtom::scopeTranslationUnit);
344 // See if any shared library also has symbol which
345 // collides with the tentative definition.
346 // SymbolTable will warn if needed.
347 _inputFiles.searchLibraries(defAtom->name(), true, false, false, *this);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000348 }
349}
350
351// get "main" atom for linkage unit
352const Atom *Resolver::entryPoint() {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000353 StringRef symbolName = _platform.entryPointName();
Nick Kledzikb334be12012-04-07 01:31:00 +0000354 if ( !symbolName.empty() )
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000355 return _symbolTable.findByName(symbolName);
356
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000357 return nullptr;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000358}
359
360// give platform a chance to tweak the set of atoms
361void Resolver::tweakAtoms() {
362 _platform.postResolveTweaks(_atoms);
363}
364
365void Resolver::linkTimeOptimize() {
366 // FIX ME
367}
368
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000369void Resolver::resolve() {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000370 this->initializeState();
371 this->addInitialUndefines();
372 this->buildInitialAtomList();
373 this->resolveUndefines();
374 this->updateReferences();
375 this->deadStripOptimize();
376 this->checkUndefines(false);
377 this->removeCoalescedAwayAtoms();
378 this->checkDylibSymbolCollisions();
379 this->linkTimeOptimize();
380 this->tweakAtoms();
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000381 this->_result.addAtoms(_atoms);
Nick Kledzikb334be12012-04-07 01:31:00 +0000382 this->_result._mainAtom = this->entryPoint();
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000383}
384
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000385void Resolver::MergedFile::addAtom(const Atom& atom) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000386 if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000387 _definedAtoms._atoms.push_back(defAtom);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000388 } else if (const UndefinedAtom* undefAtom = dyn_cast<UndefinedAtom>(&atom)) {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000389 _undefinedAtoms._atoms.push_back(undefAtom);
Michael J. Spencerb4955622012-04-02 23:56:36 +0000390 } else if (const SharedLibraryAtom* slAtom =
Michael J. Spencere6203a52012-04-03 18:39:40 +0000391 dyn_cast<SharedLibraryAtom>(&atom)) {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000392 _sharedLibraryAtoms._atoms.push_back(slAtom);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000393 } else if (const AbsoluteAtom* abAtom = dyn_cast<AbsoluteAtom>(&atom)) {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000394 _absoluteAtoms._atoms.push_back(abAtom);
Michael J. Spencerb4955622012-04-02 23:56:36 +0000395 } else {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000396 assert(0 && "atom has unknown definition kind");
397 }
398}
399
400void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
Nick Kledzik062a98c2012-04-08 23:52:13 +0000401 for ( const Atom *atom : all ) {
402 this->addAtom(*atom);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000403 }
404}
405
406
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000407} // namespace lld