blob: c895ab5e9dc0f0c620d82b1a7fffbf0b1dbb1422 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- SymbolTable.cpp ----------------------------------------------------===//
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 "SymbolTable.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000011#include "Config.h"
Sam Clegg5fa274b2018-01-10 01:13:34 +000012#include "InputChunks.h"
Sam Clegg93102972018-02-23 05:08:53 +000013#include "InputGlobal.h"
Sam Cleggb8621592017-11-30 01:40:08 +000014#include "WriterUtils.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000015#include "lld/Common/ErrorHandler.h"
Rui Ueyama2017d522017-11-28 20:39:17 +000016#include "lld/Common/Memory.h"
Rui Ueyama7d67dd12018-02-13 22:30:52 +000017#include "llvm/ADT/SetVector.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000018
19#define DEBUG_TYPE "lld"
20
21using namespace llvm;
Sam Clegg20db3812018-01-10 00:52:20 +000022using namespace llvm::wasm;
Sam Cleggc94d3932017-11-17 18:14:09 +000023using namespace lld;
24using namespace lld::wasm;
25
26SymbolTable *lld::wasm::Symtab;
27
28void SymbolTable::addFile(InputFile *File) {
29 log("Processing: " + toString(File));
30 File->parse();
31
32 if (auto *F = dyn_cast<ObjFile>(File))
33 ObjectFiles.push_back(F);
34}
35
36void SymbolTable::reportRemainingUndefines() {
Rui Ueyama7d67dd12018-02-13 22:30:52 +000037 SetVector<Symbol *> Undefs;
Sam Clegg74fe0ba2017-12-07 01:51:24 +000038 for (Symbol *Sym : SymVector) {
Sam Cleggc94d3932017-11-17 18:14:09 +000039 if (Sym->isUndefined() && !Sym->isWeak() &&
40 Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) {
41 Undefs.insert(Sym);
42 }
43 }
44
45 if (Undefs.empty())
46 return;
47
48 for (ObjFile *File : ObjectFiles)
49 for (Symbol *Sym : File->getSymbols())
50 if (Undefs.count(Sym))
51 error(toString(File) + ": undefined symbol: " + toString(*Sym));
52
53 for (Symbol *Sym : Undefs)
54 if (!Sym->getFile())
55 error("undefined symbol: " + toString(*Sym));
56}
57
58Symbol *SymbolTable::find(StringRef Name) {
Rui Ueyama67d69082018-02-28 23:03:06 +000059 return SymMap.lookup(CachedHashStringRef(Name));
Sam Cleggc94d3932017-11-17 18:14:09 +000060}
61
62std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
Sam Clegga80d94d2017-11-27 23:16:06 +000063 Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
Sam Cleggc94d3932017-11-17 18:14:09 +000064 if (Sym)
65 return {Sym, false};
Sam Cleggdfb0b2c2018-02-14 18:27:59 +000066 Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
Sam Clegg74fe0ba2017-12-07 01:51:24 +000067 SymVector.emplace_back(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +000068 return {Sym, true};
69}
70
Rui Ueyamae3498ec2018-02-28 00:09:22 +000071static void reportTypeError(const Symbol *Existing, const InputFile *File,
Sam Clegg3876d89a2018-05-14 22:42:33 +000072 llvm::wasm::WasmSymbolType Type) {
Rui Ueyamae3498ec2018-02-28 00:09:22 +000073 error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " +
74 toString(Existing->getWasmType()) + " in " +
Sam Clegg3876d89a2018-05-14 22:42:33 +000075 toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) +
76 " in " + toString(File));
Rui Ueyamae3498ec2018-02-28 00:09:22 +000077}
78
79static void checkFunctionType(const Symbol *Existing, const InputFile *File,
80 const WasmSignature *NewSig) {
Sam Clegg65d63802018-05-14 23:01:16 +000081 auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing);
82 if (!ExistingFunction) {
Sam Clegg3876d89a2018-05-14 22:42:33 +000083 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION);
Rui Ueyamae3498ec2018-02-28 00:09:22 +000084 return;
85 }
86
Sam Clegg65d63802018-05-14 23:01:16 +000087 const WasmSignature *OldSig = ExistingFunction->getFunctionType();
88 if (OldSig && NewSig && *NewSig != *OldSig) {
Sam Clegg752494b2018-05-05 01:23:07 +000089 warn("Function type mismatch: " + Existing->getName() +
90 "\n>>> defined as " + toString(*OldSig) + " in " +
91 toString(Existing->getFile()) + "\n>>> defined as " +
92 toString(*NewSig) + " in " + toString(File));
Rui Ueyamae3498ec2018-02-28 00:09:22 +000093 }
94}
95
Sam Cleggb8621592017-11-30 01:40:08 +000096// Check the type of new symbol matches that of the symbol is replacing.
97// For functions this can also involve verifying that the signatures match.
Rui Ueyamae3498ec2018-02-28 00:09:22 +000098static void checkGlobalType(const Symbol *Existing, const InputFile *File,
99 const WasmGlobalType *NewType) {
100 if (!isa<GlobalSymbol>(Existing)) {
Sam Clegg3876d89a2018-05-14 22:42:33 +0000101 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL);
Sam Cleggb8621592017-11-30 01:40:08 +0000102 return;
103 }
104
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000105 const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType();
106 if (*NewType != *OldType) {
107 error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " +
108 toString(*OldType) + " in " + toString(Existing->getFile()) +
109 "\n>>> defined as " + toString(*NewType) + " in " + toString(File));
Sam Clegg93102972018-02-23 05:08:53 +0000110 }
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000111}
112
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000113static void checkDataType(const Symbol *Existing, const InputFile *File) {
114 if (!isa<DataSymbol>(Existing))
Sam Clegg3876d89a2018-05-14 22:42:33 +0000115 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000116}
117
Sam Cleggdfb0b2c2018-02-14 18:27:59 +0000118DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
Nicholas Wilsonebda41f2018-03-09 16:43:05 +0000119 uint32_t Flags,
120 InputFunction *Function) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000121 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
Rui Ueyamab961abc2018-02-28 22:51:51 +0000122 assert(!find(Name));
Nicholas Wilsonebda41f2018-03-09 16:43:05 +0000123 SyntheticFunctions.emplace_back(Function);
124 return replaceSymbol<DefinedFunction>(insert(Name).first, Name, Flags,
125 nullptr, Function);
Sam Clegg50686852018-01-12 18:35:13 +0000126}
127
Sam Clegg00245532018-02-20 23:38:27 +0000128DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,
129 uint32_t Flags) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000130 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n");
Rui Ueyamab961abc2018-02-28 22:51:51 +0000131 assert(!find(Name));
132 return replaceSymbol<DefinedData>(insert(Name).first, Name, Flags);
Sam Cleggc94d3932017-11-17 18:14:09 +0000133}
134
Sam Clegg93102972018-02-23 05:08:53 +0000135DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags,
136 InputGlobal *Global) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000137 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global
138 << "\n");
Rui Ueyamab961abc2018-02-28 22:51:51 +0000139 assert(!find(Name));
Nicholas Wilsonebda41f2018-03-09 16:43:05 +0000140 SyntheticGlobals.emplace_back(Global);
Rui Ueyamab961abc2018-02-28 22:51:51 +0000141 return replaceSymbol<DefinedGlobal>(insert(Name).first, Name, Flags, nullptr,
142 Global);
Sam Clegg93102972018-02-23 05:08:53 +0000143}
144
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000145static bool shouldReplace(const Symbol *Existing, InputFile *NewFile,
146 uint32_t NewFlags) {
Rui Ueyamac03c9042018-02-20 21:08:47 +0000147 // If existing symbol is undefined, replace it.
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000148 if (!Existing->isDefined()) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000149 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: "
150 << Existing->getName() << "\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000151 return true;
152 }
153
154 // Now we have two defined symbols. If the new one is weak, we can ignore it.
155 if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000156 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000157 return false;
158 }
159
160 // If the existing symbol is weak, we should replace it.
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000161 if (Existing->isWeak()) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000162 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000163 return true;
164 }
165
166 // Neither symbol is week. They conflict.
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000167 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
168 toString(Existing->getFile()) + "\n>>> defined in " +
169 toString(NewFile));
Rui Ueyamac03c9042018-02-20 21:08:47 +0000170 return true;
Sam Clegg93e559b2018-02-20 18:55:06 +0000171}
172
173Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000174 InputFile *File,
175 InputFunction *Function) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000176 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
Sam Clegg93e559b2018-02-20 18:55:06 +0000177 Symbol *S;
178 bool WasInserted;
179 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000180
181 if (WasInserted || S->isLazy()) {
182 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);
183 return S;
184 }
185
186 checkFunctionType(S, File, &Function->Signature);
187
188 if (shouldReplace(S, File, Flags))
189 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);
Sam Clegg93e559b2018-02-20 18:55:06 +0000190 return S;
191}
192
Sam Clegg00245532018-02-20 23:38:27 +0000193Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags,
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000194 InputFile *File, InputSegment *Segment,
Sam Clegg93102972018-02-23 05:08:53 +0000195 uint32_t Address, uint32_t Size) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000196 LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address
197 << "\n");
Sam Clegg93e559b2018-02-20 18:55:06 +0000198 Symbol *S;
199 bool WasInserted;
200 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000201
202 if (WasInserted || S->isLazy()) {
203 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);
204 return S;
205 }
206
207 checkDataType(S, File);
208
209 if (shouldReplace(S, File, Flags))
210 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);
Sam Cleggc94d3932017-11-17 18:14:09 +0000211 return S;
212}
213
Sam Clegg93102972018-02-23 05:08:53 +0000214Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000215 InputFile *File, InputGlobal *Global) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000216 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n");
Sam Clegg93102972018-02-23 05:08:53 +0000217 Symbol *S;
218 bool WasInserted;
219 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000220
221 if (WasInserted || S->isLazy()) {
222 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);
223 return S;
224 }
225
226 checkGlobalType(S, File, &Global->getType());
227
228 if (shouldReplace(S, File, Flags))
229 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);
Sam Clegg93102972018-02-23 05:08:53 +0000230 return S;
231}
232
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000233Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags,
234 InputFile *File,
235 const WasmSignature *Sig) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000236 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000237
Sam Cleggc94d3932017-11-17 18:14:09 +0000238 Symbol *S;
239 bool WasInserted;
Sam Clegg20db3812018-01-10 00:52:20 +0000240 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000241
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000242 if (WasInserted)
243 replaceSymbol<UndefinedFunction>(S, Name, Flags, File, Sig);
244 else if (auto *Lazy = dyn_cast<LazySymbol>(S))
Rui Ueyamab961abc2018-02-28 22:51:51 +0000245 Lazy->fetch();
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000246 else if (S->isDefined())
247 checkFunctionType(S, File, Sig);
Sam Cleggc94d3932017-11-17 18:14:09 +0000248 return S;
249}
250
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000251Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags,
252 InputFile *File) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000253 LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n");
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000254
255 Symbol *S;
256 bool WasInserted;
257 std::tie(S, WasInserted) = insert(Name);
258
259 if (WasInserted)
260 replaceSymbol<UndefinedData>(S, Name, Flags, File);
261 else if (auto *Lazy = dyn_cast<LazySymbol>(S))
Rui Ueyamab961abc2018-02-28 22:51:51 +0000262 Lazy->fetch();
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000263 else if (S->isDefined())
264 checkDataType(S, File);
265 return S;
266}
267
268Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags,
269 InputFile *File,
270 const WasmGlobalType *Type) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000271 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n");
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000272
273 Symbol *S;
274 bool WasInserted;
275 std::tie(S, WasInserted) = insert(Name);
276
277 if (WasInserted)
278 replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type);
279 else if (auto *Lazy = dyn_cast<LazySymbol>(S))
Rui Ueyamab961abc2018-02-28 22:51:51 +0000280 Lazy->fetch();
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000281 else if (S->isDefined())
282 checkGlobalType(S, File, Type);
283 return S;
284}
285
286void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000287 LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000288 StringRef Name = Sym->getName();
Rui Ueyamac03c9042018-02-20 21:08:47 +0000289
Sam Cleggc94d3932017-11-17 18:14:09 +0000290 Symbol *S;
291 bool WasInserted;
292 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000293
Sam Cleggc94d3932017-11-17 18:14:09 +0000294 if (WasInserted) {
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000295 replaceSymbol<LazySymbol>(S, Name, File, *Sym);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000296 return;
297 }
298
299 // If there is an existing undefined symbol, load a new one from the archive.
300 if (S->isUndefined()) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000301 LLVM_DEBUG(dbgs() << "replacing existing undefined\n");
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000302 File->addMember(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +0000303 }
304}
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000305
Nicholas Wilsonc4d9aa12018-03-14 15:45:11 +0000306bool SymbolTable::addComdat(StringRef Name) {
307 return Comdats.insert(CachedHashStringRef(Name)).second;
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000308}