blob: e3349df6fe4547236df0b50f50de8f8a52a16319 [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() &&
Nick Kledzik233f5372013-01-15 00:17:57 +000049 (atom.scope() != DefinedAtom::scopeTranslationUnit)) {
50 // 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 Ueyamaf347e752013-11-13 23:22:00 +000054 } else if (atom.merge() == DefinedAtom::mergeByContent) {
Nick Kledzik233f5372013-01-15 00:17:57 +000055 // Named atoms cannot be merged by content.
56 assert(atom.name().empty());
Nick Kledzikbfedfc12012-01-09 20:18:15 +000057 this->addByContent(atom);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000058 }
59}
60
61enum NameCollisionResolution {
62 NCR_First,
63 NCR_Second,
Nick Kledzik6bc04c62012-02-22 21:56:59 +000064 NCR_DupDef,
65 NCR_DupUndef,
66 NCR_DupShLib,
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000067 NCR_Error
68};
69
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000070static NameCollisionResolution cases[4][4] = {
71 //regular absolute undef sharedLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000072 {
73 // first is regular
Nick Kledzik6bc04c62012-02-22 21:56:59 +000074 NCR_DupDef, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000075 },
76 {
77 // first is absolute
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000078 NCR_Error, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000079 },
80 {
81 // first is undef
Nick Kledzik6bc04c62012-02-22 21:56:59 +000082 NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000083 },
84 {
85 // first is sharedLib
Nick Kledzik6bc04c62012-02-22 21:56:59 +000086 NCR_Second, NCR_Second, NCR_First, NCR_DupShLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000087 }
88};
89
90static NameCollisionResolution collide(Atom::Definition first,
91 Atom::Definition second) {
92 return cases[first][second];
93}
94
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000095enum MergeResolution {
96 MCR_First,
97 MCR_Second,
98 MCR_Largest,
99 MCR_Error
100};
101
102static MergeResolution mergeCases[4][4] = {
103 // no tentative weak weakAddressUsed
104 {
105 // first is no
106 MCR_Error, MCR_First, MCR_First, MCR_First
107 },
108 {
109 // first is tentative
110 MCR_Second, MCR_Largest, MCR_Second, MCR_Second
111 },
112 {
113 // first is weak
114 MCR_Second, MCR_First, MCR_First, MCR_Second
115 },
116 {
117 // first is weakAddressUsed
118 MCR_Second, MCR_First, MCR_First, MCR_First
119 }
120};
121
Michael J. Spencer765792d2012-04-03 18:40:27 +0000122static MergeResolution mergeSelect(DefinedAtom::Merge first,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000123 DefinedAtom::Merge second) {
124 return mergeCases[first][second];
125}
126
Nick Kledzik38eec3d2011-12-22 02:38:01 +0000127void SymbolTable::addByName(const Atom & newAtom) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000128 StringRef name = newAtom.name();
Nick Kledzik233f5372013-01-15 00:17:57 +0000129 assert(!name.empty());
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000130 const Atom *existing = this->findByName(name);
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000131 if (existing == nullptr) {
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000132 // Name is not in symbol table yet, add it associate with this atom.
Nick Kledzik38eec3d2011-12-22 02:38:01 +0000133 _nameTable[name] = &newAtom;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000134 return;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000135 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000136
137 // Name is already in symbol table and associated with another atom.
138 bool useNew = true;
139 switch (collide(existing->definition(), newAtom.definition())) {
140 case NCR_First:
141 useNew = false;
142 break;
143 case NCR_Second:
144 useNew = true;
145 break;
146 case NCR_DupDef:
147 assert(existing->definition() == Atom::definitionRegular);
148 assert(newAtom.definition() == Atom::definitionRegular);
149 switch (mergeSelect(((DefinedAtom*)existing)->merge(),
150 ((DefinedAtom*)(&newAtom))->merge())) {
151 case MCR_First:
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000152 useNew = false;
153 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000154 case MCR_Second:
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000155 useNew = true;
156 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000157 case MCR_Largest:
158 useNew = true;
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000159 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000160 case MCR_Error:
161 llvm::errs() << "Duplicate symbols: "
162 << existing->name()
163 << ":"
164 << existing->file().path()
165 << " and "
166 << newAtom.name()
167 << ":"
168 << newAtom.file().path()
169 << "\n";
170 llvm::report_fatal_error("duplicate symbol error");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000171 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000172 }
173 break;
174 case NCR_DupUndef: {
175 const UndefinedAtom* existingUndef =
176 dyn_cast<UndefinedAtom>(existing);
177 const UndefinedAtom* newUndef =
178 dyn_cast<UndefinedAtom>(&newAtom);
179 assert(existingUndef != nullptr);
180 assert(newUndef != nullptr);
181 if (existingUndef->canBeNull() == newUndef->canBeNull()) {
182 useNew = false;
183 } else {
184 if (_context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
185 // FIXME: need diagonstics interface for writing warning messages
186 llvm::errs() << "lld warning: undefined symbol "
187 << existingUndef->name()
188 << " has different weakness in "
189 << existingUndef->file().path()
190 << " and in "
191 << newUndef->file().path();
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000192 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000193 useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
194 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000195 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000196 break;
197 case NCR_DupShLib: {
198 const SharedLibraryAtom* curShLib =
199 dyn_cast<SharedLibraryAtom>(existing);
200 const SharedLibraryAtom* newShLib =
201 dyn_cast<SharedLibraryAtom>(&newAtom);
202 assert(curShLib != nullptr);
203 assert(newShLib != nullptr);
204 bool sameNullness = (curShLib->canBeNullAtRuntime()
205 == newShLib->canBeNullAtRuntime());
206 bool sameName = curShLib->loadName().equals(newShLib->loadName());
207 if (!sameName) {
208 useNew = false;
209 if (_context.warnIfCoalesableAtomsHaveDifferentLoadName()) {
210 // FIXME: need diagonstics interface for writing warning messages
211 llvm::errs() << "lld warning: shared library symbol "
212 << curShLib->name()
213 << " has different load path in "
214 << curShLib->file().path()
215 << " and in "
216 << newShLib->file().path();
217 }
218 } else if (!sameNullness) {
219 useNew = false;
220 if (_context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
221 // FIXME: need diagonstics interface for writing warning messages
222 llvm::errs() << "lld warning: shared library symbol "
223 << curShLib->name()
224 << " has different weakness in "
225 << curShLib->file().path()
226 << " and in "
227 << newShLib->file().path();
228 }
229 } else {
230 // Both shlib atoms are identical and can be coalesced.
231 useNew = false;
232 }
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000233 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000234 break;
Rui Ueyamabcccb5d2013-11-13 23:23:38 +0000235 case NCR_Error:
236 llvm::errs() << "SymbolTable: error while merging " << name << "\n";
237 // FALLTHRU
Rui Ueyamaf347e752013-11-13 23:22:00 +0000238 default:
239 llvm::report_fatal_error("SymbolTable::addByName(): unhandled switch clause");
240 }
Rui Ueyamabcccb5d2013-11-13 23:23:38 +0000241
Rui Ueyamaf347e752013-11-13 23:22:00 +0000242 if (useNew) {
243 // Update name table to use new atom.
244 _nameTable[name] = &newAtom;
245 // Add existing atom to replacement table.
246 _replacedAtoms[existing] = &newAtom;
247 } else {
248 // New atom is not being used. Add it to replacement table.
249 _replacedAtoms[&newAtom] = existing;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000250 }
251}
252
Michael J. Spencer67f25272013-03-20 22:18:22 +0000253unsigned SymbolTable::AtomMappingInfo::getHashValue(const DefinedAtom *atom) {
254 auto content = atom->rawContent();
255 return llvm::hash_combine(atom->size(),
256 atom->contentType(),
257 llvm::hash_combine_range(content.begin(),
258 content.end()));
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000259}
260
Michael J. Spencer765792d2012-04-03 18:40:27 +0000261bool SymbolTable::AtomMappingInfo::isEqual(const DefinedAtom * const l,
Michael J. Spencer67f25272013-03-20 22:18:22 +0000262 const DefinedAtom * const r) {
Rui Ueyamaf347e752013-11-13 23:22:00 +0000263 if (l == r)
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000264 return true;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000265 if (l == getEmptyKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000266 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000267 if (r == getEmptyKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000268 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000269 if (l == getTombstoneKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000270 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000271 if (r == getTombstoneKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000272 return false;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000273
Rui Ueyamaf347e752013-11-13 23:22:00 +0000274 if (l->contentType() != r->contentType())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000275 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000276 if (l->size() != r->size())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000277 return false;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000278 ArrayRef<uint8_t> lc = l->rawContent();
279 ArrayRef<uint8_t> rc = r->rawContent();
Michael J. Spencer67f25272013-03-20 22:18:22 +0000280 return memcmp(lc.data(), rc.data(), lc.size()) == 0;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000281}
282
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000283void SymbolTable::addByContent(const DefinedAtom & newAtom) {
Nick Kledzik233f5372013-01-15 00:17:57 +0000284 // Currently only read-only constants can be merged.
285 assert(newAtom.permissions() == DefinedAtom::permR__);
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000286 AtomContentSet::iterator pos = _contentTable.find(&newAtom);
Rui Ueyamaf347e752013-11-13 23:22:00 +0000287 if (pos == _contentTable.end()) {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000288 _contentTable.insert(&newAtom);
289 return;
290 }
291 const Atom* existing = *pos;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000292 // New atom is not being used. Add it to replacement table.
293 _replacedAtoms[&newAtom] = existing;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000294}
295
Michael J. Spencere6203a52012-04-03 18:39:40 +0000296const Atom *SymbolTable::findByName(StringRef sym) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000297 NameToAtom::iterator pos = _nameTable.find(sym);
298 if (pos == _nameTable.end())
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000299 return nullptr;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000300 return pos->second;
301}
302
Michael J. Spencere6203a52012-04-03 18:39:40 +0000303bool SymbolTable::isDefined(StringRef sym) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000304 const Atom *atom = this->findByName(sym);
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000305 if (atom == nullptr)
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000306 return false;
307 if (atom->definition() == Atom::definitionUndefined)
308 return false;
309 return true;
310}
311
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000312void SymbolTable::addReplacement(const Atom *replaced,
313 const Atom *replacement) {
314 _replacedAtoms[replaced] = replacement;
315}
316
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000317const Atom *SymbolTable::replacement(const Atom *atom) {
318 AtomToAtom::iterator pos = _replacedAtoms.find(atom);
319 if (pos == _replacedAtoms.end())
320 return atom;
321 // might be chain, recurse to end
322 return this->replacement(pos->second);
323}
324
325unsigned int SymbolTable::size() {
326 return _nameTable.size();
327}
328
Michael J. Spencer280dadb2013-01-31 22:56:13 +0000329void SymbolTable::undefines(std::vector<const UndefinedAtom *> &undefs) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000330 for (NameToAtom::iterator it = _nameTable.begin(),
331 end = _nameTable.end(); it != end; ++it) {
332 const Atom *atom = it->second;
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000333 assert(atom != nullptr);
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000334 if (const auto undef = dyn_cast<const UndefinedAtom>(atom)) {
335 AtomToAtom::iterator pos = _replacedAtoms.find(undef);
336 if (pos != _replacedAtoms.end())
337 continue;
Michael J. Spencer280dadb2013-01-31 22:56:13 +0000338 undefs.push_back(undef);
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000339 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000340 }
341}
342
Nick Kledzik20e652d2012-04-20 01:24:37 +0000343void SymbolTable::tentativeDefinitions(std::vector<StringRef> &names) {
344 for (auto entry : _nameTable) {
345 const Atom *atom = entry.second;
346 StringRef name = entry.first;
347 assert(atom != nullptr);
Rui Ueyamaf347e752013-11-13 23:22:00 +0000348 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
349 if (defAtom->merge() == DefinedAtom::mergeAsTentative)
Nick Kledzik20e652d2012-04-20 01:24:37 +0000350 names.push_back(name);
Nick Kledzik20e652d2012-04-20 01:24:37 +0000351 }
352}
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000353} // namespace lld