blob: 90cd6fc62002cda8fa27ebbaff88eabe0bfaaf40 [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"
11
12#include "Config.h"
Sam Clegg5fa274b2018-01-10 01:13:34 +000013#include "InputChunks.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"
Sam Cleggc94d3932017-11-17 18:14:09 +000017
18#include <unordered_set>
19
20#define DEBUG_TYPE "lld"
21
22using namespace llvm;
Sam Clegg20db3812018-01-10 00:52:20 +000023using namespace llvm::wasm;
Sam Cleggc94d3932017-11-17 18:14:09 +000024using namespace lld;
25using namespace lld::wasm;
26
27SymbolTable *lld::wasm::Symtab;
28
29void SymbolTable::addFile(InputFile *File) {
30 log("Processing: " + toString(File));
31 File->parse();
32
33 if (auto *F = dyn_cast<ObjFile>(File))
34 ObjectFiles.push_back(F);
35}
36
37void SymbolTable::reportRemainingUndefines() {
38 std::unordered_set<Symbol *> Undefs;
Sam Clegg74fe0ba2017-12-07 01:51:24 +000039 for (Symbol *Sym : SymVector) {
Sam Cleggc94d3932017-11-17 18:14:09 +000040 if (Sym->isUndefined() && !Sym->isWeak() &&
41 Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) {
42 Undefs.insert(Sym);
43 }
44 }
45
46 if (Undefs.empty())
47 return;
48
49 for (ObjFile *File : ObjectFiles)
50 for (Symbol *Sym : File->getSymbols())
51 if (Undefs.count(Sym))
52 error(toString(File) + ": undefined symbol: " + toString(*Sym));
53
54 for (Symbol *Sym : Undefs)
55 if (!Sym->getFile())
56 error("undefined symbol: " + toString(*Sym));
57}
58
59Symbol *SymbolTable::find(StringRef Name) {
Sam Clegga80d94d2017-11-27 23:16:06 +000060 auto It = SymMap.find(CachedHashStringRef(Name));
61 if (It == SymMap.end())
Sam Cleggc94d3932017-11-17 18:14:09 +000062 return nullptr;
63 return It->second;
64}
65
66std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
Sam Clegga80d94d2017-11-27 23:16:06 +000067 Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
Sam Cleggc94d3932017-11-17 18:14:09 +000068 if (Sym)
69 return {Sym, false};
70 Sym = make<Symbol>(Name, false);
Sam Clegg74fe0ba2017-12-07 01:51:24 +000071 SymVector.emplace_back(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +000072 return {Sym, true};
73}
74
75void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
76 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
77 toString(Existing->getFile()) + "\n>>> defined in " +
Sam Clegge2ed0922017-11-27 22:49:16 +000078 toString(NewFile));
Sam Cleggc94d3932017-11-17 18:14:09 +000079}
80
Sam Cleggb8621592017-11-30 01:40:08 +000081// Check the type of new symbol matches that of the symbol is replacing.
82// For functions this can also involve verifying that the signatures match.
83static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
Sam Clegg20db3812018-01-10 00:52:20 +000084 Symbol::Kind Kind, const WasmSignature *NewSig) {
Sam Cleggb8621592017-11-30 01:40:08 +000085 if (Existing.isLazy())
Sam Cleggc94d3932017-11-17 18:14:09 +000086 return;
87
Sam Clegg20db3812018-01-10 00:52:20 +000088 bool NewIsFunction = Kind == Symbol::Kind::UndefinedFunctionKind ||
89 Kind == Symbol::Kind::DefinedFunctionKind;
Sam Cleggb8621592017-11-30 01:40:08 +000090
91 // First check the symbol types match (i.e. either both are function
92 // symbols or both are data symbols).
93 if (Existing.isFunction() != NewIsFunction) {
Sam Clegg20db3812018-01-10 00:52:20 +000094 error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " +
Sam Cleggb8621592017-11-30 01:40:08 +000095 (Existing.isFunction() ? "Function" : "Global") + " in " +
96 toString(Existing.getFile()) + "\n>>> defined as " +
97 (NewIsFunction ? "Function" : "Global") + " in " + F.getName());
98 return;
99 }
100
101 // For function symbols, optionally check the function signature matches too.
102 if (!NewIsFunction || !Config->CheckSignatures)
Sam Cleggc94d3932017-11-17 18:14:09 +0000103 return;
Sam Clegg31de2f02017-12-07 03:19:53 +0000104 // Skip the signature check if the existing function has no signature (e.g.
105 // if it is an undefined symbol generated by --undefined command line flag).
106 if (!Existing.hasFunctionType())
107 return;
Sam Cleggc94d3932017-11-17 18:14:09 +0000108
Sam Clegg20db3812018-01-10 00:52:20 +0000109 DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n");
Sam Cleggb8621592017-11-30 01:40:08 +0000110 assert(NewSig);
111
112 const WasmSignature &OldSig = Existing.getFunctionType();
113 if (*NewSig == OldSig)
114 return;
115
Sam Clegg20db3812018-01-10 00:52:20 +0000116 error("function signature mismatch: " + Existing.getName() +
117 "\n>>> defined as " + toString(OldSig) + " in " +
118 toString(Existing.getFile()) + "\n>>> defined as " + toString(*NewSig) +
119 " in " + F.getName());
Sam Cleggc94d3932017-11-17 18:14:09 +0000120}
121
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000122static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
123 Symbol::Kind Kind, const InputChunk *Chunk) {
124 const WasmSignature* Sig = nullptr;
125 if (auto* F = dyn_cast_or_null<InputFunction>(Chunk))
126 Sig = &F->Signature;
127 return checkSymbolTypes(Existing, F, Kind, Sig);
128}
129
Sam Clegg50686852018-01-12 18:35:13 +0000130Symbol *SymbolTable::addDefinedFunction(StringRef Name,
131 const WasmSignature *Type,
132 uint32_t Flags) {
133 DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
134 Symbol *S;
135 bool WasInserted;
136 std::tie(S, WasInserted) = insert(Name);
137 if (WasInserted) {
138 S->update(Symbol::DefinedFunctionKind, nullptr, Flags);
139 S->setFunctionType(Type);
140 } else if (!S->isFunction()) {
141 error("symbol type mismatch: " + Name);
Sam Clegg0f0a4282018-01-20 01:44:45 +0000142 } else if (!S->isDefined()) {
143 DEBUG(dbgs() << "resolving existing undefined function: " << Name << "\n");
144 S->update(Symbol::DefinedFunctionKind, nullptr, Flags);
Sam Clegg50686852018-01-12 18:35:13 +0000145 }
146 return S;
147}
148
Sam Cleggc94d3932017-11-17 18:14:09 +0000149Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
150 DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n");
151 Symbol *S;
152 bool WasInserted;
153 std::tie(S, WasInserted) = insert(Name);
Sam Clegg0f0a4282018-01-20 01:44:45 +0000154 if (WasInserted) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000155 S->update(Symbol::DefinedGlobalKind);
Sam Clegg0f0a4282018-01-20 01:44:45 +0000156 } else if (!S->isGlobal()) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000157 error("symbol type mismatch: " + Name);
Sam Clegg0f0a4282018-01-20 01:44:45 +0000158 } else {
159 DEBUG(dbgs() << "resolving existing undefined global: " << Name << "\n");
160 S->update(Symbol::DefinedGlobalKind);
161 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000162 return S;
163}
164
Sam Clegg20db3812018-01-10 00:52:20 +0000165Symbol *SymbolTable::addDefined(StringRef Name, Symbol::Kind Kind,
166 uint32_t Flags, InputFile *F,
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000167 InputChunk *Chunk, uint32_t Address) {
Sam Clegg20db3812018-01-10 00:52:20 +0000168 DEBUG(dbgs() << "addDefined: " << Name << " addr:" << Address << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000169 Symbol *S;
170 bool WasInserted;
Sam Cleggc94d3932017-11-17 18:14:09 +0000171
Sam Clegg20db3812018-01-10 00:52:20 +0000172 std::tie(S, WasInserted) = insert(Name);
Sam Cleggc94d3932017-11-17 18:14:09 +0000173 if (WasInserted) {
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000174 S->update(Kind, F, Flags, Chunk, Address);
Sam Cleggb8621592017-11-30 01:40:08 +0000175 } else if (S->isLazy()) {
176 // The existing symbol is lazy. Replace it without checking types since
177 // lazy symbols don't have any type information.
Sam Clegg20db3812018-01-10 00:52:20 +0000178 DEBUG(dbgs() << "replacing existing lazy symbol: " << Name << "\n");
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000179 S->update(Kind, F, Flags, Chunk, Address);
Sam Cleggc94d3932017-11-17 18:14:09 +0000180 } else if (!S->isDefined()) {
181 // The existing symbol table entry is undefined. The new symbol replaces
Sam Clegg49ed9262017-12-01 00:53:21 +0000182 // it, after checking the type matches
Sam Clegg20db3812018-01-10 00:52:20 +0000183 DEBUG(dbgs() << "resolving existing undefined symbol: " << Name << "\n");
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000184 checkSymbolTypes(*S, *F, Kind, Chunk);
185 S->update(Kind, F, Flags, Chunk, Address);
Sam Clegg20db3812018-01-10 00:52:20 +0000186 } else if ((Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000187 // the new symbol is weak we can ignore it
Sam Clegg49ed9262017-12-01 00:53:21 +0000188 DEBUG(dbgs() << "existing symbol takes precedence\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000189 } else if (S->isWeak()) {
190 // the new symbol is not weak and the existing symbol is, so we replace
191 // it
192 DEBUG(dbgs() << "replacing existing weak symbol\n");
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000193 checkSymbolTypes(*S, *F, Kind, Chunk);
194 S->update(Kind, F, Flags, Chunk, Address);
Sam Cleggc94d3932017-11-17 18:14:09 +0000195 } else {
Sam Clegg49ed9262017-12-01 00:53:21 +0000196 // neither symbol is week. They conflict.
Sam Cleggc94d3932017-11-17 18:14:09 +0000197 reportDuplicate(S, F);
198 }
199 return S;
200}
201
Sam Cleggb8621592017-11-30 01:40:08 +0000202Symbol *SymbolTable::addUndefinedFunction(StringRef Name,
203 const WasmSignature *Type) {
Sam Clegg096aa502018-01-20 01:40:17 +0000204 DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000205 Symbol *S;
206 bool WasInserted;
207 std::tie(S, WasInserted) = insert(Name);
Sam Cleggb8621592017-11-30 01:40:08 +0000208 if (WasInserted) {
Sam Clegg8d146bb2018-01-09 23:56:44 +0000209 S->update(Symbol::UndefinedFunctionKind);
210 S->setFunctionType(Type);
Sam Cleggb8621592017-11-30 01:40:08 +0000211 } else if (!S->isFunction()) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000212 error("symbol type mismatch: " + Name);
Sam Cleggb8621592017-11-30 01:40:08 +0000213 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000214 return S;
215}
216
Sam Clegg20db3812018-01-10 00:52:20 +0000217Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind,
218 uint32_t Flags, InputFile *F,
Sam Clegg8d146bb2018-01-09 23:56:44 +0000219 const WasmSignature *Type) {
Sam Clegg20db3812018-01-10 00:52:20 +0000220 DEBUG(dbgs() << "addUndefined: " << Name << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000221 Symbol *S;
222 bool WasInserted;
Sam Clegg20db3812018-01-10 00:52:20 +0000223 std::tie(S, WasInserted) = insert(Name);
Sam Cleggc94d3932017-11-17 18:14:09 +0000224 if (WasInserted) {
Sam Clegg20db3812018-01-10 00:52:20 +0000225 S->update(Kind, F, Flags);
Sam Clegg8d146bb2018-01-09 23:56:44 +0000226 if (Type)
227 S->setFunctionType(Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000228 } else if (S->isLazy()) {
229 DEBUG(dbgs() << "resolved by existing lazy\n");
230 auto *AF = cast<ArchiveFile>(S->getFile());
231 AF->addMember(&S->getArchiveSymbol());
232 } else if (S->isDefined()) {
233 DEBUG(dbgs() << "resolved by existing\n");
Sam Clegg20db3812018-01-10 00:52:20 +0000234 checkSymbolTypes(*S, *F, Kind, Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000235 }
236 return S;
237}
238
239void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
Sam Clegga681a112017-12-06 03:10:39 +0000240 DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000241 StringRef Name = Sym->getName();
242 Symbol *S;
243 bool WasInserted;
244 std::tie(S, WasInserted) = insert(Name);
245 if (WasInserted) {
246 S->update(Symbol::LazyKind, F);
247 S->setArchiveSymbol(*Sym);
248 } else if (S->isUndefined()) {
249 // There is an existing undefined symbol. The can load from the
250 // archive.
251 DEBUG(dbgs() << "replacing existing undefined\n");
252 F->addMember(Sym);
253 }
254}
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000255
256bool SymbolTable::addComdat(StringRef Name, ObjFile *F) {
257 DEBUG(dbgs() << "addComdat: " << Name << "\n");
258 ObjFile *&File = ComdatMap[CachedHashStringRef(Name)];
259 if (File) {
260 DEBUG(dbgs() << "COMDAT already defined\n");
261 return false;
262 }
263 File = F;
264 return true;
265}
266
267ObjFile *SymbolTable::findComdat(StringRef Name) const {
268 auto It = ComdatMap.find(CachedHashStringRef(Name));
269 return It == ComdatMap.end() ? nullptr : It->second;
270}