blob: 583c65acb5d385f5358de9d00d917f6896e4726d [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"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000016#include "lld/Core/LinkingContext.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000017#include "lld/Core/Resolver.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000018#include "lld/Core/SharedLibraryAtom.h"
19#include "lld/Core/UndefinedAtom.h"
Nick Kledzikbfedfc12012-01-09 20:18:15 +000020#include "llvm/ADT/ArrayRef.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000021#include "llvm/ADT/DenseMapInfo.h"
Michael J. Spencer67f25272013-03-20 22:18:22 +000022#include "llvm/ADT/Hashing.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000023#include "llvm/Support/ErrorHandling.h"
Nick Kledzikbb963df2012-04-18 21:55:06 +000024#include "llvm/Support/raw_ostream.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000025#include <algorithm>
26#include <cassert>
Michael J. Spencercfd029f2012-03-28 19:04:02 +000027#include <cstdlib>
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000028#include <vector>
29
30namespace lld {
Rui Ueyama2a522512014-05-14 17:29:27 +000031bool SymbolTable::add(const UndefinedAtom &atom) { return addByName(atom); }
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000032
Rui Ueyama2a522512014-05-14 17:29:27 +000033bool SymbolTable::add(const SharedLibraryAtom &atom) { return addByName(atom); }
Michael J. Spencer765792d2012-04-03 18:40:27 +000034
Rui Ueyama2a522512014-05-14 17:29:27 +000035bool SymbolTable::add(const AbsoluteAtom &atom) { return addByName(atom); }
Nick Kledzik6bc04c62012-02-22 21:56:59 +000036
Rui Ueyama2a522512014-05-14 17:29:27 +000037bool SymbolTable::add(const DefinedAtom &atom) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +000038 if (!atom.name().empty() &&
Rui Ueyama8b08c372013-11-25 17:09:29 +000039 atom.scope() != DefinedAtom::scopeTranslationUnit) {
Nick Kledzik233f5372013-01-15 00:17:57 +000040 // Named atoms cannot be merged by content.
41 assert(atom.merge() != DefinedAtom::mergeByContent);
42 // Track named atoms that are not scoped to file (static).
Rui Ueyama2a522512014-05-14 17:29:27 +000043 return addByName(atom);
Rui Ueyama8b08c372013-11-25 17:09:29 +000044 }
45 if (atom.merge() == DefinedAtom::mergeByContent) {
Nick Kledzik233f5372013-01-15 00:17:57 +000046 // Named atoms cannot be merged by content.
47 assert(atom.name().empty());
Nick Kledzik388f3d02014-05-28 01:16:35 +000048 // Currently only read-only constants can be merged.
49 if (atom.permissions() == DefinedAtom::permR__)
50 return addByContent(atom);
51 // TODO: support mergeByContent of data atoms by comparing content & fixups.
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000052 }
Rui Ueyama2a522512014-05-14 17:29:27 +000053 return false;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000054}
55
56enum NameCollisionResolution {
57 NCR_First,
58 NCR_Second,
Nick Kledzik6bc04c62012-02-22 21:56:59 +000059 NCR_DupDef,
60 NCR_DupUndef,
61 NCR_DupShLib,
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000062 NCR_Error
63};
64
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000065static NameCollisionResolution cases[4][4] = {
66 //regular absolute undef sharedLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000067 {
68 // first is regular
Nick Kledzik6bc04c62012-02-22 21:56:59 +000069 NCR_DupDef, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000070 },
71 {
72 // first is absolute
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000073 NCR_Error, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000074 },
75 {
76 // first is undef
Nick Kledzik6bc04c62012-02-22 21:56:59 +000077 NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000078 },
79 {
80 // first is sharedLib
Nick Kledzik6bc04c62012-02-22 21:56:59 +000081 NCR_Second, NCR_Second, NCR_First, NCR_DupShLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000082 }
83};
84
85static NameCollisionResolution collide(Atom::Definition first,
86 Atom::Definition second) {
87 return cases[first][second];
88}
89
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000090enum MergeResolution {
91 MCR_First,
92 MCR_Second,
93 MCR_Largest,
Rui Ueyamac79dd2f2014-03-07 23:05:10 +000094 MCR_SameSize,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000095 MCR_Error
96};
97
Rui Ueyama7ad72eb2014-03-18 19:37:50 +000098static MergeResolution mergeCases[][6] = {
99 // no tentative weak weakAddress sameNameAndSize largest
100 {MCR_Error, MCR_First, MCR_First, MCR_First, MCR_SameSize, MCR_Largest}, // no
101 {MCR_Second, MCR_Largest, MCR_Second, MCR_Second, MCR_SameSize, MCR_Largest}, // tentative
102 {MCR_Second, MCR_First, MCR_First, MCR_Second, MCR_SameSize, MCR_Largest}, // weak
103 {MCR_Second, MCR_First, MCR_First, MCR_First, MCR_SameSize, MCR_Largest}, // weakAddress
104 {MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize}, // sameSize
105 {MCR_Largest, MCR_Largest, MCR_Largest, MCR_Largest, MCR_SameSize, MCR_Largest}, // largest
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000106};
107
Michael J. Spencer765792d2012-04-03 18:40:27 +0000108static MergeResolution mergeSelect(DefinedAtom::Merge first,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000109 DefinedAtom::Merge second) {
Rui Ueyama7caea312014-03-08 00:44:01 +0000110 assert(first != DefinedAtom::mergeByContent);
111 assert(second != DefinedAtom::mergeByContent);
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000112 return mergeCases[first][second];
113}
114
Rui Ueyama2a522512014-05-14 17:29:27 +0000115bool SymbolTable::addByName(const Atom &newAtom) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000116 StringRef name = newAtom.name();
Nick Kledzik233f5372013-01-15 00:17:57 +0000117 assert(!name.empty());
Shankar Easwaran7ac2a3d2014-03-26 16:37:13 +0000118 const Atom *existing = findByName(name);
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000119 if (existing == nullptr) {
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000120 // Name is not in symbol table yet, add it associate with this atom.
Nick Kledzik38eec3d2011-12-22 02:38:01 +0000121 _nameTable[name] = &newAtom;
Rui Ueyama2a522512014-05-14 17:29:27 +0000122 return true;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000123 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000124
Rui Ueyama2a522512014-05-14 17:29:27 +0000125 // Do nothing if the same object is added more than once.
126 if (existing == &newAtom)
127 return false;
128
Rui Ueyamaf347e752013-11-13 23:22:00 +0000129 // 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;
Simon Atanasyan55c26992014-11-14 07:15:43 +0000138 case NCR_DupDef: {
139 const auto *existingDef = cast<DefinedAtom>(existing);
140 const auto *newDef = cast<DefinedAtom>(&newAtom);
141 switch (mergeSelect(existingDef->merge(), newDef->merge())) {
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000142 case MCR_First:
143 useNew = false;
144 break;
145 case MCR_Second:
146 useNew = true;
147 break;
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000148 case MCR_Largest: {
Rui Ueyama77a4da12015-03-04 21:40:46 +0000149 uint64_t existingSize = existingDef->sectionSize();
150 uint64_t newSize = newDef->sectionSize();
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000151 useNew = (newSize >= existingSize);
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000152 break;
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000153 }
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000154 case MCR_SameSize: {
Rui Ueyama77a4da12015-03-04 21:40:46 +0000155 uint64_t existingSize = existingDef->sectionSize();
156 uint64_t newSize = newDef->sectionSize();
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000157 if (existingSize == newSize) {
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000158 useNew = true;
159 break;
160 }
161 llvm::errs() << "Size mismatch: "
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000162 << existing->name() << " (" << existingSize << ") "
163 << newAtom.name() << " (" << newSize << ")\n";
Galina Kistanova91d62c92017-06-07 06:46:38 +0000164 LLVM_FALLTHROUGH;
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000165 }
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000166 case MCR_Error:
Rui Ueyamabe5e0b02016-02-28 21:59:02 +0000167 llvm::errs() << "Duplicate symbols: "
168 << existing->name()
169 << ":"
170 << existing->file().path()
171 << " and "
172 << newAtom.name()
173 << ":"
174 << newAtom.file().path()
175 << "\n";
176 llvm::report_fatal_error("duplicate symbol error");
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000177 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000178 }
179 break;
Simon Atanasyan55c26992014-11-14 07:15:43 +0000180 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000181 case NCR_DupUndef: {
Rui Ueyama01cc7182014-04-04 18:21:51 +0000182 const UndefinedAtom* existingUndef = cast<UndefinedAtom>(existing);
183 const UndefinedAtom* newUndef = cast<UndefinedAtom>(&newAtom);
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000184
185 bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000186 if (sameCanBeNull)
Rafael Espindolac778aa42016-02-28 16:27:08 +0000187 useNew = false;
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000188 else
189 useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
Rui Ueyamaf347e752013-11-13 23:22:00 +0000190 break;
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000191 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000192 case NCR_DupShLib: {
Rui Ueyamae8af3e42014-04-04 18:21:53 +0000193 useNew = false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000194 break;
Rui Ueyamafb7936d2014-04-04 18:12:27 +0000195 }
Rui Ueyamabcccb5d2013-11-13 23:23:38 +0000196 case NCR_Error:
197 llvm::errs() << "SymbolTable: error while merging " << name << "\n";
Rui Ueyama9310e012013-11-14 06:39:31 +0000198 llvm::report_fatal_error("duplicate symbol error");
199 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000200 }
Rui Ueyamabcccb5d2013-11-13 23:23:38 +0000201
Rui Ueyamaf347e752013-11-13 23:22:00 +0000202 if (useNew) {
203 // Update name table to use new atom.
204 _nameTable[name] = &newAtom;
205 // Add existing atom to replacement table.
206 _replacedAtoms[existing] = &newAtom;
207 } else {
208 // New atom is not being used. Add it to replacement table.
209 _replacedAtoms[&newAtom] = existing;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000210 }
Rui Ueyama2a522512014-05-14 17:29:27 +0000211 return false;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000212}
213
Michael J. Spencer67f25272013-03-20 22:18:22 +0000214unsigned SymbolTable::AtomMappingInfo::getHashValue(const DefinedAtom *atom) {
215 auto content = atom->rawContent();
216 return llvm::hash_combine(atom->size(),
217 atom->contentType(),
218 llvm::hash_combine_range(content.begin(),
219 content.end()));
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000220}
221
Michael J. Spencer765792d2012-04-03 18:40:27 +0000222bool SymbolTable::AtomMappingInfo::isEqual(const DefinedAtom * const l,
Michael J. Spencer67f25272013-03-20 22:18:22 +0000223 const DefinedAtom * const r) {
Rui Ueyamaf347e752013-11-13 23:22:00 +0000224 if (l == r)
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000225 return true;
Davide Italiano0f672ed2016-08-12 12:34:39 +0000226 if (l == getEmptyKey() || r == getEmptyKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000227 return false;
Davide Italiano0f672ed2016-08-12 12:34:39 +0000228 if (l == getTombstoneKey() || r == getTombstoneKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000229 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000230 if (l->contentType() != r->contentType())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000231 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000232 if (l->size() != r->size())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000233 return false;
Nick Kledzik32d0d092014-10-02 17:22:05 +0000234 if (l->sectionChoice() != r->sectionChoice())
235 return false;
236 if (l->sectionChoice() == DefinedAtom::sectionCustomRequired) {
237 if (!l->customSectionName().equals(r->customSectionName()))
238 return false;
239 }
Michael J. Spencere6203a52012-04-03 18:39:40 +0000240 ArrayRef<uint8_t> lc = l->rawContent();
241 ArrayRef<uint8_t> rc = r->rawContent();
Michael J. Spencer67f25272013-03-20 22:18:22 +0000242 return memcmp(lc.data(), rc.data(), lc.size()) == 0;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000243}
244
Rui Ueyama2a522512014-05-14 17:29:27 +0000245bool SymbolTable::addByContent(const DefinedAtom &newAtom) {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000246 AtomContentSet::iterator pos = _contentTable.find(&newAtom);
Rui Ueyamaf347e752013-11-13 23:22:00 +0000247 if (pos == _contentTable.end()) {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000248 _contentTable.insert(&newAtom);
Rui Ueyama2a522512014-05-14 17:29:27 +0000249 return true;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000250 }
251 const Atom* existing = *pos;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000252 // New atom is not being used. Add it to replacement table.
253 _replacedAtoms[&newAtom] = existing;
Rui Ueyama2a522512014-05-14 17:29:27 +0000254 return false;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000255}
256
Michael J. Spencere6203a52012-04-03 18:39:40 +0000257const Atom *SymbolTable::findByName(StringRef sym) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000258 NameToAtom::iterator pos = _nameTable.find(sym);
259 if (pos == _nameTable.end())
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000260 return nullptr;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000261 return pos->second;
262}
263
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000264const Atom *SymbolTable::replacement(const Atom *atom) {
Rui Ueyama1c3486a2014-04-03 22:58:41 +0000265 // Find the replacement for a given atom. Atoms in _replacedAtoms
266 // may be chained, so find the last one.
Rui Ueyama4f010d22014-04-03 22:36:55 +0000267 for (;;) {
268 AtomToAtom::iterator pos = _replacedAtoms.find(atom);
269 if (pos == _replacedAtoms.end())
270 return atom;
Rui Ueyama4f010d22014-04-03 22:36:55 +0000271 atom = pos->second;
272 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000273}
274
Rui Ueyama733b45f2014-06-05 07:37:29 +0000275bool SymbolTable::isCoalescedAway(const Atom *atom) {
276 return _replacedAtoms.count(atom) > 0;
277}
278
Rui Ueyama8dc9f0a2014-04-04 00:15:52 +0000279std::vector<const UndefinedAtom *> SymbolTable::undefines() {
280 std::vector<const UndefinedAtom *> ret;
Rui Ueyama17e899c2013-11-25 17:09:27 +0000281 for (auto it : _nameTable) {
282 const Atom *atom = it.second;
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000283 assert(atom != nullptr);
Rui Ueyama839fb2f2014-08-22 02:00:58 +0000284 if (const auto *undef = dyn_cast<const UndefinedAtom>(atom))
285 if (_replacedAtoms.count(undef) == 0)
286 ret.push_back(undef);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000287 }
Rui Ueyama8dc9f0a2014-04-04 00:15:52 +0000288 return ret;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000289}
290
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000291} // namespace lld