173
|
1 //===- SymbolTable.cpp ----------------------------------------------------===//
|
|
2 //
|
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4 // See https://llvm.org/LICENSE.txt for license information.
|
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8
|
|
9 #include "SymbolTable.h"
|
207
|
10 #include "Config.h"
|
173
|
11 #include "InputFiles.h"
|
|
12 #include "Symbols.h"
|
|
13 #include "lld/Common/ErrorHandler.h"
|
|
14 #include "lld/Common/Memory.h"
|
|
15
|
|
16 using namespace llvm;
|
|
17 using namespace lld;
|
|
18 using namespace lld::macho;
|
|
19
|
207
|
20 Symbol *SymbolTable::find(CachedHashStringRef cachedName) {
|
|
21 auto it = symMap.find(cachedName);
|
173
|
22 if (it == symMap.end())
|
|
23 return nullptr;
|
|
24 return symVector[it->second];
|
|
25 }
|
|
26
|
207
|
27 std::pair<Symbol *, bool> SymbolTable::insert(StringRef name,
|
|
28 const InputFile *file) {
|
173
|
29 auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
|
|
30
|
207
|
31 Symbol *sym;
|
|
32 if (!p.second) {
|
|
33 // Name already present in the symbol table.
|
|
34 sym = symVector[p.first->second];
|
|
35 } else {
|
|
36 // Name is a new symbol.
|
|
37 sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
|
|
38 symVector.push_back(sym);
|
|
39 }
|
173
|
40
|
207
|
41 sym->isUsedInRegularObj |= !file || isa<ObjFile>(file);
|
|
42 return {sym, p.second};
|
173
|
43 }
|
|
44
|
207
|
45 Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
|
|
46 InputSection *isec, uint64_t value,
|
|
47 uint64_t size, bool isWeakDef,
|
|
48 bool isPrivateExtern, bool isThumb,
|
|
49 bool isReferencedDynamically,
|
|
50 bool noDeadStrip) {
|
173
|
51 Symbol *s;
|
|
52 bool wasInserted;
|
207
|
53 bool overridesWeakDef = false;
|
|
54 std::tie(s, wasInserted) = insert(name, file);
|
|
55
|
|
56 assert(!isWeakDef || (isa<BitcodeFile>(file) && !isec) ||
|
|
57 (isa<ObjFile>(file) && file == isec->file));
|
|
58
|
|
59 if (!wasInserted) {
|
|
60 if (auto *defined = dyn_cast<Defined>(s)) {
|
|
61 if (isWeakDef) {
|
|
62 if (defined->isWeakDef()) {
|
|
63 // Both old and new symbol weak (e.g. inline function in two TUs):
|
|
64 // If one of them isn't private extern, the merged symbol isn't.
|
|
65 defined->privateExtern &= isPrivateExtern;
|
|
66 defined->referencedDynamically |= isReferencedDynamically;
|
|
67 defined->noDeadStrip |= noDeadStrip;
|
|
68
|
|
69 // FIXME: Handle this for bitcode files.
|
|
70 // FIXME: We currently only do this if both symbols are weak.
|
|
71 // We could do this if either is weak (but getting the
|
|
72 // case where !isWeakDef && defined->isWeakDef() right
|
|
73 // requires some care and testing).
|
|
74 if (isec)
|
|
75 isec->wasCoalesced = true;
|
|
76 }
|
173
|
77
|
207
|
78 return defined;
|
|
79 }
|
|
80 if (!defined->isWeakDef())
|
|
81 error("duplicate symbol: " + name + "\n>>> defined in " +
|
|
82 toString(defined->getFile()) + "\n>>> defined in " +
|
|
83 toString(file));
|
|
84 } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) {
|
|
85 overridesWeakDef = !isWeakDef && dysym->isWeakDef();
|
|
86 dysym->unreference();
|
|
87 }
|
|
88 // Defined symbols take priority over other types of symbols, so in case
|
|
89 // of a name conflict, we fall through to the replaceSymbol() call below.
|
|
90 }
|
173
|
91
|
207
|
92 Defined *defined = replaceSymbol<Defined>(
|
|
93 s, name, file, isec, value, size, isWeakDef, /*isExternal=*/true,
|
|
94 isPrivateExtern, isThumb, isReferencedDynamically, noDeadStrip);
|
|
95 defined->overridesWeakDef = overridesWeakDef;
|
|
96 return defined;
|
|
97 }
|
|
98
|
|
99 Symbol *SymbolTable::addUndefined(StringRef name, InputFile *file,
|
|
100 bool isWeakRef) {
|
|
101 Symbol *s;
|
|
102 bool wasInserted;
|
|
103 std::tie(s, wasInserted) = insert(name, file);
|
|
104
|
|
105 RefState refState = isWeakRef ? RefState::Weak : RefState::Strong;
|
|
106
|
|
107 if (wasInserted)
|
|
108 replaceSymbol<Undefined>(s, name, file, refState);
|
|
109 else if (auto *lazy = dyn_cast<LazySymbol>(s))
|
|
110 lazy->fetchArchiveMember();
|
|
111 else if (auto *dynsym = dyn_cast<DylibSymbol>(s))
|
|
112 dynsym->reference(refState);
|
|
113 else if (auto *undefined = dyn_cast<Undefined>(s))
|
|
114 undefined->refState = std::max(undefined->refState, refState);
|
173
|
115 return s;
|
|
116 }
|
|
117
|
207
|
118 Symbol *SymbolTable::addCommon(StringRef name, InputFile *file, uint64_t size,
|
|
119 uint32_t align, bool isPrivateExtern) {
|
173
|
120 Symbol *s;
|
|
121 bool wasInserted;
|
207
|
122 std::tie(s, wasInserted) = insert(name, file);
|
173
|
123
|
207
|
124 if (!wasInserted) {
|
|
125 if (auto *common = dyn_cast<CommonSymbol>(s)) {
|
|
126 if (size < common->size)
|
|
127 return s;
|
|
128 } else if (isa<Defined>(s)) {
|
|
129 return s;
|
|
130 }
|
|
131 // Common symbols take priority over all non-Defined symbols, so in case of
|
|
132 // a name conflict, we fall through to the replaceSymbol() call below.
|
|
133 }
|
|
134
|
|
135 replaceSymbol<CommonSymbol>(s, name, file, size, align, isPrivateExtern);
|
173
|
136 return s;
|
|
137 }
|
|
138
|
207
|
139 Symbol *SymbolTable::addDylib(StringRef name, DylibFile *file, bool isWeakDef,
|
|
140 bool isTlv) {
|
173
|
141 Symbol *s;
|
|
142 bool wasInserted;
|
207
|
143 std::tie(s, wasInserted) = insert(name, file);
|
173
|
144
|
207
|
145 RefState refState = RefState::Unreferenced;
|
|
146 if (!wasInserted) {
|
|
147 if (auto *defined = dyn_cast<Defined>(s)) {
|
|
148 if (isWeakDef && !defined->isWeakDef())
|
|
149 defined->overridesWeakDef = true;
|
|
150 } else if (auto *undefined = dyn_cast<Undefined>(s)) {
|
|
151 refState = undefined->refState;
|
|
152 } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) {
|
|
153 refState = dysym->getRefState();
|
|
154 }
|
|
155 }
|
|
156
|
|
157 bool isDynamicLookup = file == nullptr;
|
|
158 if (wasInserted || isa<Undefined>(s) ||
|
|
159 (isa<DylibSymbol>(s) &&
|
|
160 ((!isWeakDef && s->isWeakDef()) ||
|
|
161 (!isDynamicLookup && cast<DylibSymbol>(s)->isDynamicLookup())))) {
|
|
162 if (auto *dynsym = dyn_cast<DylibSymbol>(s))
|
|
163 dynsym->unreference();
|
|
164 replaceSymbol<DylibSymbol>(s, file, name, isWeakDef, refState, isTlv);
|
|
165 }
|
|
166
|
173
|
167 return s;
|
|
168 }
|
|
169
|
207
|
170 Symbol *SymbolTable::addDynamicLookup(StringRef name) {
|
|
171 return addDylib(name, /*file=*/nullptr, /*isWeakDef=*/false, /*isTlv=*/false);
|
|
172 }
|
|
173
|
173
|
174 Symbol *SymbolTable::addLazy(StringRef name, ArchiveFile *file,
|
207
|
175 const object::Archive::Symbol &sym) {
|
173
|
176 Symbol *s;
|
|
177 bool wasInserted;
|
207
|
178 std::tie(s, wasInserted) = insert(name, file);
|
173
|
179
|
|
180 if (wasInserted)
|
|
181 replaceSymbol<LazySymbol>(s, file, sym);
|
207
|
182 else if (isa<Undefined>(s) || (isa<DylibSymbol>(s) && s->isWeakDef()))
|
173
|
183 file->fetch(sym);
|
|
184 return s;
|
|
185 }
|
|
186
|
207
|
187 Defined *SymbolTable::addSynthetic(StringRef name, InputSection *isec,
|
|
188 uint64_t value, bool isPrivateExtern,
|
|
189 bool includeInSymtab,
|
|
190 bool referencedDynamically) {
|
|
191 Defined *s = addDefined(name, nullptr, isec, value, /*size=*/0,
|
|
192 /*isWeakDef=*/false, isPrivateExtern,
|
|
193 /*isThumb=*/false, referencedDynamically,
|
|
194 /*noDeadStrip=*/false);
|
|
195 s->includeInSymtab = includeInSymtab;
|
|
196 return s;
|
|
197 }
|
|
198
|
|
199 void lld::macho::treatUndefinedSymbol(const Undefined &sym, StringRef source) {
|
|
200 auto message = [source, &sym]() {
|
|
201 std::string message = "undefined symbol: " + toString(sym);
|
|
202 if (!source.empty())
|
|
203 message += "\n>>> referenced by " + source.str();
|
|
204 else
|
|
205 message += "\n>>> referenced by " + toString(sym.getFile());
|
|
206 return message;
|
|
207 };
|
|
208 switch (config->undefinedSymbolTreatment) {
|
|
209 case UndefinedSymbolTreatment::error:
|
|
210 error(message());
|
|
211 break;
|
|
212 case UndefinedSymbolTreatment::warning:
|
|
213 warn(message());
|
|
214 LLVM_FALLTHROUGH;
|
|
215 case UndefinedSymbolTreatment::dynamic_lookup:
|
|
216 case UndefinedSymbolTreatment::suppress:
|
|
217 symtab->addDynamicLookup(sym.getName());
|
|
218 break;
|
|
219 case UndefinedSymbolTreatment::unknown:
|
|
220 llvm_unreachable("unknown -undefined TREATMENT");
|
|
221 }
|
|
222 }
|
|
223
|
173
|
224 SymbolTable *macho::symtab;
|