blob: f81afe23fafb0c1db297ac0e55533d130a436981 [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 Cleggc94d3932017-11-17 18:14:09 +000013#include "Strings.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;
23using 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() {
37 std::unordered_set<Symbol *> Undefs;
Sam Clegga80d94d2017-11-27 23:16:06 +000038 for (auto &I : SymMap) {
Sam Cleggc94d3932017-11-17 18:14:09 +000039 Symbol *Sym = I.second;
40 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);
71 return {Sym, true};
72}
73
74void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
75 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
76 toString(Existing->getFile()) + "\n>>> defined in " +
Sam Clegge2ed0922017-11-27 22:49:16 +000077 toString(NewFile));
Sam Cleggc94d3932017-11-17 18:14:09 +000078}
79
Sam Cleggb8621592017-11-30 01:40:08 +000080// Get the signature for a given function symbol, either by looking
81// it up in function sections (for defined functions), of the imports section
82// (for imported functions).
83static const WasmSignature *getFunctionSig(const ObjFile &Obj,
84 const WasmSymbol &Sym) {
85 DEBUG(dbgs() << "getFunctionSig: " << Sym.Name << "\n");
86 const WasmObjectFile *WasmObj = Obj.getWasmObj();
87 uint32_t FunctionType;
88 if (Obj.isImportedFunction(Sym.ElementIndex)) {
89 const WasmImport &Import = WasmObj->imports()[Sym.ImportIndex];
90 FunctionType = Import.SigIndex;
91 } else {
92 uint32_t FuntionIndex = Sym.ElementIndex - Obj.NumFunctionImports();
93 FunctionType = WasmObj->functionTypes()[FuntionIndex];
94 }
95 return &WasmObj->types()[FunctionType];
96}
97
98// Check the type of new symbol matches that of the symbol is replacing.
99// For functions this can also involve verifying that the signatures match.
100static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
101 const WasmSymbol &New,
102 const WasmSignature *NewSig) {
103 if (Existing.isLazy())
Sam Cleggc94d3932017-11-17 18:14:09 +0000104 return;
105
Sam Cleggb8621592017-11-30 01:40:08 +0000106 bool NewIsFunction = New.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT ||
107 New.Type == WasmSymbol::SymbolType::FUNCTION_IMPORT;
108
109 // First check the symbol types match (i.e. either both are function
110 // symbols or both are data symbols).
111 if (Existing.isFunction() != NewIsFunction) {
112 error("symbol type mismatch: " + New.Name + "\n>>> defined as " +
113 (Existing.isFunction() ? "Function" : "Global") + " in " +
114 toString(Existing.getFile()) + "\n>>> defined as " +
115 (NewIsFunction ? "Function" : "Global") + " in " + F.getName());
116 return;
117 }
118
119 // For function symbols, optionally check the function signature matches too.
120 if (!NewIsFunction || !Config->CheckSignatures)
Sam Cleggc94d3932017-11-17 18:14:09 +0000121 return;
122
Sam Cleggb8621592017-11-30 01:40:08 +0000123 DEBUG(dbgs() << "checkSymbolTypes: " << New.Name << "\n");
124 assert(NewSig);
125
126 const WasmSignature &OldSig = Existing.getFunctionType();
127 if (*NewSig == OldSig)
128 return;
129
130 error("function signature mismatch: " + New.Name + "\n>>> defined as " +
131 toString(OldSig) + " in " + toString(Existing.getFile()) +
132 "\n>>> defined as " + toString(*NewSig) + " in " + F.getName());
Sam Cleggc94d3932017-11-17 18:14:09 +0000133}
134
135Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
136 DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n");
137 Symbol *S;
138 bool WasInserted;
139 std::tie(S, WasInserted) = insert(Name);
140 if (WasInserted)
141 S->update(Symbol::DefinedGlobalKind);
142 else if (!S->isGlobal())
143 error("symbol type mismatch: " + Name);
144 return S;
145}
146
147Symbol *SymbolTable::addDefined(InputFile *F, const WasmSymbol *Sym,
148 const InputSegment *Segment) {
149 DEBUG(dbgs() << "addDefined: " << Sym->Name << "\n");
150 Symbol *S;
151 bool WasInserted;
152 Symbol::Kind Kind = Symbol::DefinedFunctionKind;
Sam Cleggb8621592017-11-30 01:40:08 +0000153 const WasmSignature *NewSig = nullptr;
Sam Cleggc94d3932017-11-17 18:14:09 +0000154 if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
155 Kind = Symbol::DefinedGlobalKind;
Sam Cleggb8621592017-11-30 01:40:08 +0000156 else
157 NewSig = getFunctionSig(*cast<ObjFile>(F), *Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +0000158
159 std::tie(S, WasInserted) = insert(Sym->Name);
160 if (WasInserted) {
Sam Cleggb8621592017-11-30 01:40:08 +0000161 S->update(Kind, F, Sym, Segment, NewSig);
162 } else if (S->isLazy()) {
163 // The existing symbol is lazy. Replace it without checking types since
164 // lazy symbols don't have any type information.
165 DEBUG(dbgs() << "replacing existing lazy symbol: " << Sym->Name << "\n");
166 S->update(Kind, F, Sym, Segment, NewSig);
Sam Cleggc94d3932017-11-17 18:14:09 +0000167 } else if (!S->isDefined()) {
168 // The existing symbol table entry is undefined. The new symbol replaces
Sam Clegg49ed9262017-12-01 00:53:21 +0000169 // it, after checking the type matches
Sam Cleggc94d3932017-11-17 18:14:09 +0000170 DEBUG(dbgs() << "resolving existing undefined symbol: " << Sym->Name
171 << "\n");
Sam Cleggb8621592017-11-30 01:40:08 +0000172 checkSymbolTypes(*S, *F, *Sym, NewSig);
173 S->update(Kind, F, Sym, Segment, NewSig);
Sam Cleggc94d3932017-11-17 18:14:09 +0000174 } else if (Sym->isWeak()) {
175 // the new symbol is weak we can ignore it
Sam Clegg49ed9262017-12-01 00:53:21 +0000176 DEBUG(dbgs() << "existing symbol takes precedence\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000177 } else if (S->isWeak()) {
178 // the new symbol is not weak and the existing symbol is, so we replace
179 // it
180 DEBUG(dbgs() << "replacing existing weak symbol\n");
Sam Cleggb8621592017-11-30 01:40:08 +0000181 checkSymbolTypes(*S, *F, *Sym, NewSig);
182 S->update(Kind, F, Sym, Segment, NewSig);
Sam Cleggc94d3932017-11-17 18:14:09 +0000183 } else {
Sam Clegg49ed9262017-12-01 00:53:21 +0000184 // neither symbol is week. They conflict.
Sam Cleggc94d3932017-11-17 18:14:09 +0000185 reportDuplicate(S, F);
186 }
187 return S;
188}
189
Sam Cleggb8621592017-11-30 01:40:08 +0000190Symbol *SymbolTable::addUndefinedFunction(StringRef Name,
191 const WasmSignature *Type) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000192 Symbol *S;
193 bool WasInserted;
194 std::tie(S, WasInserted) = insert(Name);
Sam Cleggb8621592017-11-30 01:40:08 +0000195 if (WasInserted) {
196 S->update(Symbol::UndefinedFunctionKind, nullptr, nullptr, nullptr, Type);
197 } else if (!S->isFunction()) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000198 error("symbol type mismatch: " + Name);
Sam Cleggb8621592017-11-30 01:40:08 +0000199 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000200 return S;
201}
202
203Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym) {
204 DEBUG(dbgs() << "addUndefined: " << displayName(Sym->Name) << "\n");
205 Symbol *S;
206 bool WasInserted;
207 Symbol::Kind Kind = Symbol::UndefinedFunctionKind;
Sam Cleggb8621592017-11-30 01:40:08 +0000208 const WasmSignature *NewSig = nullptr;
Sam Cleggc94d3932017-11-17 18:14:09 +0000209 if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_IMPORT)
210 Kind = Symbol::UndefinedGlobalKind;
Sam Cleggb8621592017-11-30 01:40:08 +0000211 else
212 NewSig = getFunctionSig(*cast<ObjFile>(F), *Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +0000213 std::tie(S, WasInserted) = insert(Sym->Name);
214 if (WasInserted) {
Sam Cleggb8621592017-11-30 01:40:08 +0000215 S->update(Kind, F, Sym, nullptr, NewSig);
Sam Cleggc94d3932017-11-17 18:14:09 +0000216 } else if (S->isLazy()) {
217 DEBUG(dbgs() << "resolved by existing lazy\n");
218 auto *AF = cast<ArchiveFile>(S->getFile());
219 AF->addMember(&S->getArchiveSymbol());
220 } else if (S->isDefined()) {
221 DEBUG(dbgs() << "resolved by existing\n");
Sam Cleggb8621592017-11-30 01:40:08 +0000222 checkSymbolTypes(*S, *F, *Sym, NewSig);
Sam Cleggc94d3932017-11-17 18:14:09 +0000223 }
224 return S;
225}
226
227void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
228 DEBUG(dbgs() << "addLazy: " << displayName(Sym->getName()) << "\n");
229 StringRef Name = Sym->getName();
230 Symbol *S;
231 bool WasInserted;
232 std::tie(S, WasInserted) = insert(Name);
233 if (WasInserted) {
234 S->update(Symbol::LazyKind, F);
235 S->setArchiveSymbol(*Sym);
236 } else if (S->isUndefined()) {
237 // There is an existing undefined symbol. The can load from the
238 // archive.
239 DEBUG(dbgs() << "replacing existing undefined\n");
240 F->addMember(Sym);
241 }
242}