blob: a6089116da56af8ed2c8af6f22b8cd92f75744d7 [file] [log] [blame]
Michael J. Spencer773a8fb2011-12-18 08:27:59 +00001//===- Core/SymbolTable.cpp - Main Symbol Table ---------------------------===//
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
10#include "lld/Core/SymbolTable.h"
Nick Kledzik6bc04c62012-02-22 21:56:59 +000011#include "lld/Core/AbsoluteAtom.h"
Michael J. Spencer4586fbc2013-01-22 20:49:42 +000012#include "lld/Core/Atom.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000013#include "lld/Core/DefinedAtom.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000014#include "lld/Core/File.h"
Michael J. Spencere6203a52012-04-03 18:39:40 +000015#include "lld/Core/LLVM.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000016#include "lld/Core/Resolver.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000017#include "lld/Core/SharedLibraryAtom.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000018#include "lld/Core/LinkingContext.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000019#include "lld/Core/UndefinedAtom.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000020
Nick Kledzikbfedfc12012-01-09 20:18:15 +000021#include "llvm/ADT/ArrayRef.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000022#include "llvm/ADT/DenseMapInfo.h"
Michael J. Spencer67f25272013-03-20 22:18:22 +000023#include "llvm/ADT/Hashing.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000024#include "llvm/Support/ErrorHandling.h"
Nick Kledzikbb963df2012-04-18 21:55:06 +000025#include "llvm/Support/raw_ostream.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000026
27#include <algorithm>
28#include <cassert>
Michael J. Spencercfd029f2012-03-28 19:04:02 +000029#include <cstdlib>
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000030#include <vector>
31
32namespace lld {
Rui Ueyama0ca149f2013-08-06 22:31:59 +000033SymbolTable::SymbolTable(const LinkingContext &context) : _context(context) {}
Nick Kledzik38eec3d2011-12-22 02:38:01 +000034
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000035void SymbolTable::add(const UndefinedAtom &atom) {
36 this->addByName(atom);
37}
38
Nick Kledzik6bc04c62012-02-22 21:56:59 +000039void SymbolTable::add(const SharedLibraryAtom &atom) {
40 this->addByName(atom);
41}
Michael J. Spencer765792d2012-04-03 18:40:27 +000042
Nick Kledzik6bc04c62012-02-22 21:56:59 +000043void SymbolTable::add(const AbsoluteAtom &atom) {
44 this->addByName(atom);
45}
46
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000047void SymbolTable::add(const DefinedAtom &atom) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +000048 if (!atom.name().empty() &&
Rui Ueyama8b08c372013-11-25 17:09:29 +000049 atom.scope() != DefinedAtom::scopeTranslationUnit) {
Nick Kledzik233f5372013-01-15 00:17:57 +000050 // Named atoms cannot be merged by content.
51 assert(atom.merge() != DefinedAtom::mergeByContent);
52 // Track named atoms that are not scoped to file (static).
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000053 this->addByName(atom);
Rui Ueyama8b08c372013-11-25 17:09:29 +000054 return;
55 }
56 if (atom.merge() == DefinedAtom::mergeByContent) {
Nick Kledzik233f5372013-01-15 00:17:57 +000057 // Named atoms cannot be merged by content.
58 assert(atom.name().empty());
Nick Kledzikbfedfc12012-01-09 20:18:15 +000059 this->addByContent(atom);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000060 }
61}
62
63enum NameCollisionResolution {
64 NCR_First,
65 NCR_Second,
Nick Kledzik6bc04c62012-02-22 21:56:59 +000066 NCR_DupDef,
67 NCR_DupUndef,
68 NCR_DupShLib,
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000069 NCR_Error
70};
71
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000072static NameCollisionResolution cases[4][4] = {
73 //regular absolute undef sharedLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000074 {
75 // first is regular
Nick Kledzik6bc04c62012-02-22 21:56:59 +000076 NCR_DupDef, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000077 },
78 {
79 // first is absolute
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000080 NCR_Error, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000081 },
82 {
83 // first is undef
Nick Kledzik6bc04c62012-02-22 21:56:59 +000084 NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000085 },
86 {
87 // first is sharedLib
Nick Kledzik6bc04c62012-02-22 21:56:59 +000088 NCR_Second, NCR_Second, NCR_First, NCR_DupShLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000089 }
90};
91
92static NameCollisionResolution collide(Atom::Definition first,
93 Atom::Definition second) {
94 return cases[first][second];
95}
96
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000097enum MergeResolution {
98 MCR_First,
99 MCR_Second,
100 MCR_Largest,
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000101 MCR_SameSize,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000102 MCR_Error
103};
104
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000105static MergeResolution mergeCases[][5] = {
106 // no tentative weak weakAddress sameNameAndSize
107 {MCR_Error, MCR_First, MCR_First, MCR_First, MCR_SameSize}, // no
108 {MCR_Second, MCR_Largest, MCR_Second, MCR_Second, MCR_SameSize}, // tentative
109 {MCR_Second, MCR_First, MCR_First, MCR_Second, MCR_SameSize}, // weak
110 {MCR_Second, MCR_First, MCR_First, MCR_First, MCR_SameSize}, // weakAddress
111 {MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize}, // sameSize
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000112};
113
Michael J. Spencer765792d2012-04-03 18:40:27 +0000114static MergeResolution mergeSelect(DefinedAtom::Merge first,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000115 DefinedAtom::Merge second) {
116 return mergeCases[first][second];
117}
118
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000119void SymbolTable::addByName(const Atom &newAtom) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000120 StringRef name = newAtom.name();
Nick Kledzik233f5372013-01-15 00:17:57 +0000121 assert(!name.empty());
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000122 const Atom *existing = this->findByName(name);
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000123 if (existing == nullptr) {
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000124 // Name is not in symbol table yet, add it associate with this atom.
Nick Kledzik38eec3d2011-12-22 02:38:01 +0000125 _nameTable[name] = &newAtom;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000126 return;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000127 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000128
129 // Name is already in symbol table and associated with another atom.
130 bool useNew = true;
131 switch (collide(existing->definition(), newAtom.definition())) {
132 case NCR_First:
133 useNew = false;
134 break;
135 case NCR_Second:
136 useNew = true;
137 break;
138 case NCR_DupDef:
139 assert(existing->definition() == Atom::definitionRegular);
140 assert(newAtom.definition() == Atom::definitionRegular);
141 switch (mergeSelect(((DefinedAtom*)existing)->merge(),
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000142 ((DefinedAtom*)&newAtom)->merge())) {
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000143 case MCR_First:
144 useNew = false;
145 break;
146 case MCR_Second:
147 useNew = true;
148 break;
149 case MCR_Largest:
150 useNew = true;
151 break;
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000152 case MCR_SameSize: {
153 uint64_t sa = ((DefinedAtom*)existing)->size();
154 uint64_t sb = ((DefinedAtom*)&newAtom)->size();
155 if (sa == sb) {
156 useNew = true;
157 break;
158 }
159 llvm::errs() << "Size mismatch: "
160 << existing->name() << " (" << sa << ") "
161 << newAtom.name() << " (" << sb << ")\n";
162 // fallthrough
163 }
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000164 case MCR_Error:
165 llvm::errs() << "Duplicate symbols: "
166 << existing->name()
167 << ":"
168 << existing->file().path()
169 << " and "
170 << newAtom.name()
171 << ":"
172 << newAtom.file().path()
173 << "\n";
174 llvm::report_fatal_error("duplicate symbol error");
175 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000176 }
177 break;
178 case NCR_DupUndef: {
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000179 const UndefinedAtom* existingUndef = dyn_cast<UndefinedAtom>(existing);
180 const UndefinedAtom* newUndef = dyn_cast<UndefinedAtom>(&newAtom);
181 assert(existingUndef != nullptr);
182 assert(newUndef != nullptr);
183
184 bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
185 if (!sameCanBeNull &&
186 _context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
187 llvm::errs() << "lld warning: undefined symbol "
188 << existingUndef->name()
189 << " has different weakness in "
190 << existingUndef->file().path()
191 << " and in " << newUndef->file().path() << "\n";
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000192 }
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000193
194 const UndefinedAtom *existingFallback = existingUndef->fallback();
195 const UndefinedAtom *newFallback = newUndef->fallback();
196 bool hasDifferentFallback =
197 (existingFallback && newFallback &&
198 existingFallback->name() != newFallback->name());
199 if (hasDifferentFallback) {
200 llvm::errs() << "lld warning: undefined symbol "
201 << existingUndef->name() << " has different fallback: "
202 << existingFallback->name() << " in "
203 << existingUndef->file().path() << " and "
204 << newFallback->name() << " in "
205 << newUndef->file().path() << "\n";
206 }
207
208 bool hasNewFallback = newUndef->fallback();
209 if (sameCanBeNull)
210 useNew = hasNewFallback;
211 else
212 useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
Rui Ueyamaf347e752013-11-13 23:22:00 +0000213 break;
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000214 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000215 case NCR_DupShLib: {
216 const SharedLibraryAtom* curShLib =
217 dyn_cast<SharedLibraryAtom>(existing);
218 const SharedLibraryAtom* newShLib =
219 dyn_cast<SharedLibraryAtom>(&newAtom);
220 assert(curShLib != nullptr);
221 assert(newShLib != nullptr);
222 bool sameNullness = (curShLib->canBeNullAtRuntime()
223 == newShLib->canBeNullAtRuntime());
224 bool sameName = curShLib->loadName().equals(newShLib->loadName());
225 if (!sameName) {
226 useNew = false;
227 if (_context.warnIfCoalesableAtomsHaveDifferentLoadName()) {
228 // FIXME: need diagonstics interface for writing warning messages
229 llvm::errs() << "lld warning: shared library symbol "
230 << curShLib->name()
231 << " has different load path in "
232 << curShLib->file().path()
233 << " and in "
234 << newShLib->file().path();
235 }
236 } else if (!sameNullness) {
237 useNew = false;
238 if (_context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
239 // FIXME: need diagonstics interface for writing warning messages
240 llvm::errs() << "lld warning: shared library symbol "
241 << curShLib->name()
242 << " has different weakness in "
243 << curShLib->file().path()
244 << " and in "
245 << newShLib->file().path();
246 }
247 } else {
248 // Both shlib atoms are identical and can be coalesced.
249 useNew = false;
250 }
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000251 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000252 break;
Rui Ueyamabcccb5d2013-11-13 23:23:38 +0000253 case NCR_Error:
254 llvm::errs() << "SymbolTable: error while merging " << name << "\n";
Rui Ueyama9310e012013-11-14 06:39:31 +0000255 llvm::report_fatal_error("duplicate symbol error");
256 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000257 }
Rui Ueyamabcccb5d2013-11-13 23:23:38 +0000258
Rui Ueyamaf347e752013-11-13 23:22:00 +0000259 if (useNew) {
260 // Update name table to use new atom.
261 _nameTable[name] = &newAtom;
262 // Add existing atom to replacement table.
263 _replacedAtoms[existing] = &newAtom;
264 } else {
265 // New atom is not being used. Add it to replacement table.
266 _replacedAtoms[&newAtom] = existing;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000267 }
268}
269
Michael J. Spencer67f25272013-03-20 22:18:22 +0000270unsigned SymbolTable::AtomMappingInfo::getHashValue(const DefinedAtom *atom) {
271 auto content = atom->rawContent();
272 return llvm::hash_combine(atom->size(),
273 atom->contentType(),
274 llvm::hash_combine_range(content.begin(),
275 content.end()));
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000276}
277
Michael J. Spencer765792d2012-04-03 18:40:27 +0000278bool SymbolTable::AtomMappingInfo::isEqual(const DefinedAtom * const l,
Michael J. Spencer67f25272013-03-20 22:18:22 +0000279 const DefinedAtom * const r) {
Rui Ueyamaf347e752013-11-13 23:22:00 +0000280 if (l == r)
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000281 return true;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000282 if (l == getEmptyKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000283 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000284 if (r == getEmptyKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000285 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000286 if (l == getTombstoneKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000287 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000288 if (r == getTombstoneKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000289 return false;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000290
Rui Ueyamaf347e752013-11-13 23:22:00 +0000291 if (l->contentType() != r->contentType())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000292 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000293 if (l->size() != r->size())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000294 return false;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000295 ArrayRef<uint8_t> lc = l->rawContent();
296 ArrayRef<uint8_t> rc = r->rawContent();
Michael J. Spencer67f25272013-03-20 22:18:22 +0000297 return memcmp(lc.data(), rc.data(), lc.size()) == 0;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000298}
299
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000300void SymbolTable::addByContent(const DefinedAtom & newAtom) {
Nick Kledzik233f5372013-01-15 00:17:57 +0000301 // Currently only read-only constants can be merged.
302 assert(newAtom.permissions() == DefinedAtom::permR__);
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000303 AtomContentSet::iterator pos = _contentTable.find(&newAtom);
Rui Ueyamaf347e752013-11-13 23:22:00 +0000304 if (pos == _contentTable.end()) {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000305 _contentTable.insert(&newAtom);
306 return;
307 }
308 const Atom* existing = *pos;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000309 // New atom is not being used. Add it to replacement table.
310 _replacedAtoms[&newAtom] = existing;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000311}
312
Michael J. Spencere6203a52012-04-03 18:39:40 +0000313const Atom *SymbolTable::findByName(StringRef sym) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000314 NameToAtom::iterator pos = _nameTable.find(sym);
315 if (pos == _nameTable.end())
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000316 return nullptr;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000317 return pos->second;
318}
319
Michael J. Spencere6203a52012-04-03 18:39:40 +0000320bool SymbolTable::isDefined(StringRef sym) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000321 const Atom *atom = this->findByName(sym);
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000322 if (atom == nullptr)
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000323 return false;
Rui Ueyama69c71cc2013-11-18 22:42:03 +0000324 return atom->definition() != Atom::definitionUndefined;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000325}
326
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000327void SymbolTable::addReplacement(const Atom *replaced,
328 const Atom *replacement) {
329 _replacedAtoms[replaced] = replacement;
330}
331
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000332const Atom *SymbolTable::replacement(const Atom *atom) {
333 AtomToAtom::iterator pos = _replacedAtoms.find(atom);
334 if (pos == _replacedAtoms.end())
335 return atom;
336 // might be chain, recurse to end
337 return this->replacement(pos->second);
338}
339
340unsigned int SymbolTable::size() {
341 return _nameTable.size();
342}
343
Michael J. Spencer280dadb2013-01-31 22:56:13 +0000344void SymbolTable::undefines(std::vector<const UndefinedAtom *> &undefs) {
Rui Ueyama17e899c2013-11-25 17:09:27 +0000345 for (auto it : _nameTable) {
346 const Atom *atom = it.second;
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000347 assert(atom != nullptr);
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000348 if (const auto undef = dyn_cast<const UndefinedAtom>(atom)) {
349 AtomToAtom::iterator pos = _replacedAtoms.find(undef);
350 if (pos != _replacedAtoms.end())
351 continue;
Michael J. Spencer280dadb2013-01-31 22:56:13 +0000352 undefs.push_back(undef);
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000353 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000354 }
355}
356
Nick Kledzik20e652d2012-04-20 01:24:37 +0000357void SymbolTable::tentativeDefinitions(std::vector<StringRef> &names) {
358 for (auto entry : _nameTable) {
359 const Atom *atom = entry.second;
360 StringRef name = entry.first;
361 assert(atom != nullptr);
Rui Ueyamaf347e752013-11-13 23:22:00 +0000362 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
363 if (defAtom->merge() == DefinedAtom::mergeAsTentative)
Nick Kledzik20e652d2012-04-20 01:24:37 +0000364 names.push_back(name);
Nick Kledzik20e652d2012-04-20 01:24:37 +0000365 }
366}
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000367} // namespace lld