blob: d8d7be9f0459d0b302e637ae6b4aeb70b7c32fe1 [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) {
Sam Clegga80d94d2017-11-27 23:16:06 +000059 auto It = SymMap.find(CachedHashStringRef(Name));
60 if (It == SymMap.end())
Sam Cleggc94d3932017-11-17 18:14:09 +000061 return nullptr;
62 return It->second;
63}
64
65std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
Sam Clegga80d94d2017-11-27 23:16:06 +000066 Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
Sam Cleggc94d3932017-11-17 18:14:09 +000067 if (Sym)
68 return {Sym, false};
Sam Cleggdfb0b2c2018-02-14 18:27:59 +000069 Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
Sam Clegg74fe0ba2017-12-07 01:51:24 +000070 SymVector.emplace_back(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +000071 return {Sym, true};
72}
73
Sam Cleggb8621592017-11-30 01:40:08 +000074// Check the type of new symbol matches that of the symbol is replacing.
75// For functions this can also involve verifying that the signatures match.
76static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
Sam Clegg93102972018-02-23 05:08:53 +000077 WasmSymbolType NewType,
78 const WasmSignature *NewFunctionSig,
79 const WasmGlobalType *NewGlobalType) {
Sam Cleggb8621592017-11-30 01:40:08 +000080 if (Existing.isLazy())
Sam Cleggc94d3932017-11-17 18:14:09 +000081 return;
82
Sam Clegg93102972018-02-23 05:08:53 +000083 WasmSymbolType ExistingType = Existing.getWasmType();
84
Sam Cleggb8621592017-11-30 01:40:08 +000085 // First check the symbol types match (i.e. either both are function
86 // symbols or both are data symbols).
Sam Clegg93102972018-02-23 05:08:53 +000087 if (NewType != ExistingType) {
Sam Clegg20db3812018-01-10 00:52:20 +000088 error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " +
Sam Clegg93102972018-02-23 05:08:53 +000089 toString(ExistingType) + " in " + toString(Existing.getFile()) +
90 "\n>>> defined as " + toString(NewType) + " in " + F.getName());
Sam Cleggb8621592017-11-30 01:40:08 +000091 return;
92 }
93
Sam Clegg93102972018-02-23 05:08:53 +000094 // For function/global symbols, optionally check the type matches too.
95 if (NewType == WASM_SYMBOL_TYPE_DATA || !Config->CheckSignatures)
Sam Cleggc94d3932017-11-17 18:14:09 +000096 return;
Sam Cleggdfb0b2c2018-02-14 18:27:59 +000097
Sam Clegg93102972018-02-23 05:08:53 +000098 DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n");
Sam Clegg3f8db982018-02-16 23:50:23 +000099
Sam Clegg93102972018-02-23 05:08:53 +0000100 auto ReportError = [&](const Twine &Old, const Twine &New) {
101 error(toString(NewType) + " type mismatch: " + Existing.getName() +
102 "\n>>> defined as " + Old + " in " + toString(Existing.getFile()) +
103 "\n>>> defined as " + New + " in " + F.getName());
104 };
Sam Cleggc94d3932017-11-17 18:14:09 +0000105
Sam Clegg93102972018-02-23 05:08:53 +0000106 if (NewType == WASM_SYMBOL_TYPE_FUNCTION) {
107 // Skip the signature check if the existing function has no signature (e.g.
108 // if it is an undefined symbol generated by --undefined command line flag).
109 auto &Sym = cast<FunctionSymbol>(Existing);
110 const WasmSignature *OldSig = Sym.getFunctionType();
111 if (!OldSig)
112 return;
Sam Cleggb8621592017-11-30 01:40:08 +0000113
Sam Clegg93102972018-02-23 05:08:53 +0000114 assert(NewFunctionSig);
115 if (*NewFunctionSig == *OldSig)
116 return;
Sam Cleggb8621592017-11-30 01:40:08 +0000117
Sam Clegg93102972018-02-23 05:08:53 +0000118 ReportError(toString(*OldSig), toString(*NewFunctionSig));
119 } else {
120 auto &Sym = cast<GlobalSymbol>(Existing);
Sam Cleggc94d3932017-11-17 18:14:09 +0000121
Sam Clegg93102972018-02-23 05:08:53 +0000122 assert(NewGlobalType != nullptr);
123 const WasmGlobalType *OldType = Sym.getGlobalType();
124 if (*NewGlobalType == *OldType)
125 return;
126
127 ReportError(toString(*OldType), toString(*NewGlobalType));
128 }
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000129}
130
Sam Cleggdfb0b2c2018-02-14 18:27:59 +0000131DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
132 const WasmSignature *Type,
133 uint32_t Flags) {
Sam Clegga1892302018-02-13 20:14:26 +0000134 DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
Sam Clegg50686852018-01-12 18:35:13 +0000135 Symbol *S;
136 bool WasInserted;
137 std::tie(S, WasInserted) = insert(Name);
Sam Clegga1892302018-02-13 20:14:26 +0000138 assert(WasInserted);
Sam Cleggdfb0b2c2018-02-14 18:27:59 +0000139 return replaceSymbol<DefinedFunction>(S, Name, Flags, Type);
Sam Clegg50686852018-01-12 18:35:13 +0000140}
141
Sam Clegg00245532018-02-20 23:38:27 +0000142DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,
143 uint32_t Flags) {
144 DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000145 Symbol *S;
146 bool WasInserted;
147 std::tie(S, WasInserted) = insert(Name);
Sam Clegga1892302018-02-13 20:14:26 +0000148 assert(WasInserted);
Sam Clegg00245532018-02-20 23:38:27 +0000149 return replaceSymbol<DefinedData>(S, Name, Flags);
Sam Cleggc94d3932017-11-17 18:14:09 +0000150}
151
Sam Clegg93102972018-02-23 05:08:53 +0000152DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags,
153 InputGlobal *Global) {
154 DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global << "\n");
155 Symbol *S;
156 bool WasInserted;
157 std::tie(S, WasInserted) = insert(Name);
158 assert(WasInserted);
159 return replaceSymbol<DefinedGlobal>(S, Name, Flags, nullptr, Global);
160}
161
Sam Cleggf60b0d52018-02-20 18:55:07 +0000162static bool shouldReplace(const Symbol &Existing, InputFile *NewFile,
Sam Clegg93102972018-02-23 05:08:53 +0000163 WasmSymbolType NewType, uint32_t NewFlags,
164 const WasmSignature *NewFuncType = nullptr,
165 const WasmGlobalType *NewGlobalType = nullptr) {
166
Rui Ueyamac03c9042018-02-20 21:08:47 +0000167 // If existing symbol is lazy, replace it without checking types since
168 // lazy symbols don't have any type information.
Sam Clegg93e559b2018-02-20 18:55:06 +0000169 if (Existing.isLazy()) {
Sam Clegg93e559b2018-02-20 18:55:06 +0000170 DEBUG(dbgs() << "replacing existing lazy symbol: " << Existing.getName()
171 << "\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000172 return true;
Sam Cleggc94d3932017-11-17 18:14:09 +0000173 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000174
Rui Ueyamac03c9042018-02-20 21:08:47 +0000175 // Now we have two wasm symbols, and all wasm symbols that have the same
176 // symbol name must have the same type, even if they are undefined. This
177 // is different from ELF because symbol types are not that significant
178 // in ELF, and undefined symbols in ELF don't have type in the first place.
Sam Clegg93102972018-02-23 05:08:53 +0000179 checkSymbolTypes(Existing, *NewFile, NewType, NewFuncType, NewGlobalType);
Sam Clegg93e559b2018-02-20 18:55:06 +0000180
Rui Ueyamac03c9042018-02-20 21:08:47 +0000181 // If existing symbol is undefined, replace it.
182 if (!Existing.isDefined()) {
183 DEBUG(dbgs() << "resolving existing undefined symbol: "
184 << Existing.getName() << "\n");
185 return true;
186 }
187
188 // Now we have two defined symbols. If the new one is weak, we can ignore it.
189 if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
190 DEBUG(dbgs() << "existing symbol takes precedence\n");
191 return false;
192 }
193
194 // If the existing symbol is weak, we should replace it.
195 if (Existing.isWeak()) {
196 DEBUG(dbgs() << "replacing existing weak symbol\n");
197 return true;
198 }
199
200 // Neither symbol is week. They conflict.
201 error("duplicate symbol: " + toString(Existing) + "\n>>> defined in " +
202 toString(Existing.getFile()) + "\n>>> defined in " + toString(NewFile));
203 return true;
Sam Clegg93e559b2018-02-20 18:55:06 +0000204}
205
206Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
207 InputFile *F, InputFunction *Function) {
208 DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
209 Symbol *S;
210 bool WasInserted;
211 std::tie(S, WasInserted) = insert(Name);
Sam Clegg93102972018-02-23 05:08:53 +0000212 if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_FUNCTION, Flags,
213 &Function->Signature))
Sam Clegg93e559b2018-02-20 18:55:06 +0000214 replaceSymbol<DefinedFunction>(S, Name, Flags, F, Function);
215 return S;
216}
217
Sam Clegg00245532018-02-20 23:38:27 +0000218Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags,
Sam Clegg93102972018-02-23 05:08:53 +0000219 InputFile *F, InputSegment *Segment,
220 uint32_t Address, uint32_t Size) {
Sam Clegg00245532018-02-20 23:38:27 +0000221 DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address << "\n");
Sam Clegg93e559b2018-02-20 18:55:06 +0000222 Symbol *S;
223 bool WasInserted;
224 std::tie(S, WasInserted) = insert(Name);
Sam Clegg93102972018-02-23 05:08:53 +0000225 if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_DATA, Flags))
226 replaceSymbol<DefinedData>(S, Name, Flags, F, Segment, Address, Size);
Sam Cleggc94d3932017-11-17 18:14:09 +0000227 return S;
228}
229
Sam Clegg93102972018-02-23 05:08:53 +0000230Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,
231 InputFile *F, InputGlobal *Global) {
232 DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n");
233 Symbol *S;
234 bool WasInserted;
235 std::tie(S, WasInserted) = insert(Name);
236 if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_GLOBAL, Flags,
237 nullptr, &Global->getType()))
238 replaceSymbol<DefinedGlobal>(S, Name, Flags, F, Global);
239 return S;
240}
241
242Symbol *SymbolTable::addUndefined(StringRef Name, WasmSymbolType Type,
Sam Clegg20db3812018-01-10 00:52:20 +0000243 uint32_t Flags, InputFile *F,
Sam Clegg93102972018-02-23 05:08:53 +0000244 const WasmSignature *FunctionType,
245 const WasmGlobalType *GlobalType) {
246 DEBUG(dbgs() << "addUndefined type=" << Type << ": " << Name << "\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000247
Sam Cleggc94d3932017-11-17 18:14:09 +0000248 Symbol *S;
249 bool WasInserted;
Sam Clegg20db3812018-01-10 00:52:20 +0000250 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000251
Sam Cleggc94d3932017-11-17 18:14:09 +0000252 if (WasInserted) {
Sam Clegg93102972018-02-23 05:08:53 +0000253 switch (Type) {
254 case WASM_SYMBOL_TYPE_FUNCTION:
255 replaceSymbol<UndefinedFunction>(S, Name, Flags, F, FunctionType);
256 break;
257 case WASM_SYMBOL_TYPE_GLOBAL:
258 replaceSymbol<UndefinedGlobal>(S, Name, Flags, F, GlobalType);
259 break;
260 case WASM_SYMBOL_TYPE_DATA:
Sam Clegg00245532018-02-20 23:38:27 +0000261 replaceSymbol<UndefinedData>(S, Name, Flags, F);
Sam Clegg93102972018-02-23 05:08:53 +0000262 break;
263 }
Rui Ueyamac03c9042018-02-20 21:08:47 +0000264 return S;
265 }
266
267 if (auto *Lazy = dyn_cast<LazySymbol>(S)) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000268 DEBUG(dbgs() << "resolved by existing lazy\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000269 cast<ArchiveFile>(Lazy->getFile())->addMember(&Lazy->getArchiveSymbol());
270 return S;
271 }
272
273 if (S->isDefined()) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000274 DEBUG(dbgs() << "resolved by existing\n");
Sam Clegg93102972018-02-23 05:08:53 +0000275 checkSymbolTypes(*S, *F, Type, FunctionType, GlobalType);
Sam Cleggc94d3932017-11-17 18:14:09 +0000276 }
Sam Clegg93102972018-02-23 05:08:53 +0000277
Sam Cleggc94d3932017-11-17 18:14:09 +0000278 return S;
279}
280
281void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
Sam Clegga681a112017-12-06 03:10:39 +0000282 DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000283 StringRef Name = Sym->getName();
Rui Ueyamac03c9042018-02-20 21:08:47 +0000284
Sam Cleggc94d3932017-11-17 18:14:09 +0000285 Symbol *S;
286 bool WasInserted;
287 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000288
Sam Cleggc94d3932017-11-17 18:14:09 +0000289 if (WasInserted) {
Sam Cleggdfb0b2c2018-02-14 18:27:59 +0000290 replaceSymbol<LazySymbol>(S, Name, F, *Sym);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000291 return;
292 }
293
294 // If there is an existing undefined symbol, load a new one from the archive.
295 if (S->isUndefined()) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000296 DEBUG(dbgs() << "replacing existing undefined\n");
297 F->addMember(Sym);
298 }
299}
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000300
301bool SymbolTable::addComdat(StringRef Name, ObjFile *F) {
302 DEBUG(dbgs() << "addComdat: " << Name << "\n");
303 ObjFile *&File = ComdatMap[CachedHashStringRef(Name)];
304 if (File) {
305 DEBUG(dbgs() << "COMDAT already defined\n");
306 return false;
307 }
308 File = F;
309 return true;
310}
311
312ObjFile *SymbolTable::findComdat(StringRef Name) const {
313 auto It = ComdatMap.find(CachedHashStringRef(Name));
314 return It == ComdatMap.end() ? nullptr : It->second;
315}