blob: a21ed8319047f215fae0a573fc17c9c570bdffff [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 Clegg50686852018-01-12 18:35:13 +0000122Symbol *SymbolTable::addDefinedFunction(StringRef Name,
123 const WasmSignature *Type,
124 uint32_t Flags) {
125 DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
126 Symbol *S;
127 bool WasInserted;
128 std::tie(S, WasInserted) = insert(Name);
129 if (WasInserted) {
130 S->update(Symbol::DefinedFunctionKind, nullptr, Flags);
131 S->setFunctionType(Type);
132 } else if (!S->isFunction()) {
133 error("symbol type mismatch: " + Name);
134 }
135 return S;
136}
137
Sam Cleggc94d3932017-11-17 18:14:09 +0000138Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
139 DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n");
140 Symbol *S;
141 bool WasInserted;
142 std::tie(S, WasInserted) = insert(Name);
143 if (WasInserted)
144 S->update(Symbol::DefinedGlobalKind);
145 else if (!S->isGlobal())
146 error("symbol type mismatch: " + Name);
147 return S;
148}
149
Sam Clegg20db3812018-01-10 00:52:20 +0000150Symbol *SymbolTable::addDefined(StringRef Name, Symbol::Kind Kind,
151 uint32_t Flags, InputFile *F,
Sam Clegg8d146bb2018-01-09 23:56:44 +0000152 const InputSegment *Segment,
Sam Clegg20db3812018-01-10 00:52:20 +0000153 InputFunction *Function, uint32_t Address) {
154 DEBUG(dbgs() << "addDefined: " << Name << " addr:" << Address << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000155 Symbol *S;
156 bool WasInserted;
Sam Cleggc94d3932017-11-17 18:14:09 +0000157
Sam Clegg20db3812018-01-10 00:52:20 +0000158 std::tie(S, WasInserted) = insert(Name);
Sam Cleggc94d3932017-11-17 18:14:09 +0000159 if (WasInserted) {
Sam Clegg20db3812018-01-10 00:52:20 +0000160 S->update(Kind, F, Flags, Segment, Function, Address);
Sam Cleggb8621592017-11-30 01:40:08 +0000161 } else if (S->isLazy()) {
162 // The existing symbol is lazy. Replace it without checking types since
163 // lazy symbols don't have any type information.
Sam Clegg20db3812018-01-10 00:52:20 +0000164 DEBUG(dbgs() << "replacing existing lazy symbol: " << Name << "\n");
165 S->update(Kind, F, Flags, Segment, Function, Address);
Sam Cleggc94d3932017-11-17 18:14:09 +0000166 } else if (!S->isDefined()) {
167 // The existing symbol table entry is undefined. The new symbol replaces
Sam Clegg49ed9262017-12-01 00:53:21 +0000168 // it, after checking the type matches
Sam Clegg20db3812018-01-10 00:52:20 +0000169 DEBUG(dbgs() << "resolving existing undefined symbol: " << Name << "\n");
170 checkSymbolTypes(*S, *F, Kind, Function ? &Function->Signature : nullptr);
171 S->update(Kind, F, Flags, Segment, Function, Address);
172 } else if ((Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000173 // the new symbol is weak we can ignore it
Sam Clegg49ed9262017-12-01 00:53:21 +0000174 DEBUG(dbgs() << "existing symbol takes precedence\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000175 } else if (S->isWeak()) {
176 // the new symbol is not weak and the existing symbol is, so we replace
177 // it
178 DEBUG(dbgs() << "replacing existing weak symbol\n");
Sam Clegg20db3812018-01-10 00:52:20 +0000179 checkSymbolTypes(*S, *F, Kind, Function ? &Function->Signature : nullptr);
180 S->update(Kind, F, Flags, Segment, Function, Address);
Sam Cleggc94d3932017-11-17 18:14:09 +0000181 } else {
Sam Clegg49ed9262017-12-01 00:53:21 +0000182 // neither symbol is week. They conflict.
Sam Cleggc94d3932017-11-17 18:14:09 +0000183 reportDuplicate(S, F);
184 }
185 return S;
186}
187
Sam Cleggb8621592017-11-30 01:40:08 +0000188Symbol *SymbolTable::addUndefinedFunction(StringRef Name,
189 const WasmSignature *Type) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000190 Symbol *S;
191 bool WasInserted;
192 std::tie(S, WasInserted) = insert(Name);
Sam Cleggb8621592017-11-30 01:40:08 +0000193 if (WasInserted) {
Sam Clegg8d146bb2018-01-09 23:56:44 +0000194 S->update(Symbol::UndefinedFunctionKind);
195 S->setFunctionType(Type);
Sam Cleggb8621592017-11-30 01:40:08 +0000196 } else if (!S->isFunction()) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000197 error("symbol type mismatch: " + Name);
Sam Cleggb8621592017-11-30 01:40:08 +0000198 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000199 return S;
200}
201
Sam Clegg20db3812018-01-10 00:52:20 +0000202Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind,
203 uint32_t Flags, InputFile *F,
Sam Clegg8d146bb2018-01-09 23:56:44 +0000204 const WasmSignature *Type) {
Sam Clegg20db3812018-01-10 00:52:20 +0000205 DEBUG(dbgs() << "addUndefined: " << Name << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000206 Symbol *S;
207 bool WasInserted;
Sam Clegg20db3812018-01-10 00:52:20 +0000208 std::tie(S, WasInserted) = insert(Name);
Sam Cleggc94d3932017-11-17 18:14:09 +0000209 if (WasInserted) {
Sam Clegg20db3812018-01-10 00:52:20 +0000210 S->update(Kind, F, Flags);
Sam Clegg8d146bb2018-01-09 23:56:44 +0000211 if (Type)
212 S->setFunctionType(Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000213 } else if (S->isLazy()) {
214 DEBUG(dbgs() << "resolved by existing lazy\n");
215 auto *AF = cast<ArchiveFile>(S->getFile());
216 AF->addMember(&S->getArchiveSymbol());
217 } else if (S->isDefined()) {
218 DEBUG(dbgs() << "resolved by existing\n");
Sam Clegg20db3812018-01-10 00:52:20 +0000219 checkSymbolTypes(*S, *F, Kind, Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000220 }
221 return S;
222}
223
224void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
Sam Clegga681a112017-12-06 03:10:39 +0000225 DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000226 StringRef Name = Sym->getName();
227 Symbol *S;
228 bool WasInserted;
229 std::tie(S, WasInserted) = insert(Name);
230 if (WasInserted) {
231 S->update(Symbol::LazyKind, F);
232 S->setArchiveSymbol(*Sym);
233 } else if (S->isUndefined()) {
234 // There is an existing undefined symbol. The can load from the
235 // archive.
236 DEBUG(dbgs() << "replacing existing undefined\n");
237 F->addMember(Sym);
238 }
239}
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000240
241bool SymbolTable::addComdat(StringRef Name, ObjFile *F) {
242 DEBUG(dbgs() << "addComdat: " << Name << "\n");
243 ObjFile *&File = ComdatMap[CachedHashStringRef(Name)];
244 if (File) {
245 DEBUG(dbgs() << "COMDAT already defined\n");
246 return false;
247 }
248 File = F;
249 return true;
250}
251
252ObjFile *SymbolTable::findComdat(StringRef Name) const {
253 auto It = ComdatMap.find(CachedHashStringRef(Name));
254 return It == ComdatMap.end() ? nullptr : It->second;
255}