blob: 77b2f18c2863b77120b09aff84cb5e2ce2ec42a2 [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
Sam Cleggc729c1b2018-05-30 18:07:52 +000032 // LLVM bitcode file
33 if (auto *F = dyn_cast<BitcodeFile>(File))
34 BitcodeFiles.push_back(F);
35 else if (auto *F = dyn_cast<ObjFile>(File))
Sam Cleggc94d3932017-11-17 18:14:09 +000036 ObjectFiles.push_back(F);
37}
38
Sam Cleggc729c1b2018-05-30 18:07:52 +000039// This function is where all the optimizations of link-time
40// optimization happens. When LTO is in use, some input files are
41// not in native object file format but in the LLVM bitcode format.
42// This function compiles bitcode files into a few big native files
43// using LLVM functions and replaces bitcode symbols with the results.
44// Because all bitcode files that the program consists of are passed
45// to the compiler at once, it can do whole-program optimization.
46void SymbolTable::addCombinedLTOObject() {
47 if (BitcodeFiles.empty())
48 return;
49
50 // Compile bitcode files and replace bitcode symbols.
51 LTO.reset(new BitcodeCompiler);
52 for (BitcodeFile *F : BitcodeFiles)
53 LTO->add(*F);
54
55 for (StringRef Filename : LTO->compile()) {
56 auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp"));
57 Obj->parse();
58 ObjectFiles.push_back(Obj);
59 }
60}
61
Sam Cleggc94d3932017-11-17 18:14:09 +000062void SymbolTable::reportRemainingUndefines() {
Rui Ueyama7d67dd12018-02-13 22:30:52 +000063 SetVector<Symbol *> Undefs;
Sam Clegg74fe0ba2017-12-07 01:51:24 +000064 for (Symbol *Sym : SymVector) {
Sam Cleggc729c1b2018-05-30 18:07:52 +000065 if (!Sym->isUndefined() || Sym->isWeak())
66 continue;
67 if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0)
68 continue;
69 if (!Sym->IsUsedInRegularObj)
70 continue;
71 Undefs.insert(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +000072 }
73
74 if (Undefs.empty())
75 return;
76
77 for (ObjFile *File : ObjectFiles)
78 for (Symbol *Sym : File->getSymbols())
79 if (Undefs.count(Sym))
80 error(toString(File) + ": undefined symbol: " + toString(*Sym));
81
82 for (Symbol *Sym : Undefs)
83 if (!Sym->getFile())
84 error("undefined symbol: " + toString(*Sym));
85}
86
87Symbol *SymbolTable::find(StringRef Name) {
Rui Ueyama67d69082018-02-28 23:03:06 +000088 return SymMap.lookup(CachedHashStringRef(Name));
Sam Cleggc94d3932017-11-17 18:14:09 +000089}
90
91std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
Sam Clegga80d94d2017-11-27 23:16:06 +000092 Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
Sam Cleggc94d3932017-11-17 18:14:09 +000093 if (Sym)
94 return {Sym, false};
Sam Cleggdfb0b2c2018-02-14 18:27:59 +000095 Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
Sam Cleggc729c1b2018-05-30 18:07:52 +000096 Sym->IsUsedInRegularObj = false;
Sam Clegg74fe0ba2017-12-07 01:51:24 +000097 SymVector.emplace_back(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +000098 return {Sym, true};
99}
100
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000101static void reportTypeError(const Symbol *Existing, const InputFile *File,
Sam Clegg3876d89a2018-05-14 22:42:33 +0000102 llvm::wasm::WasmSymbolType Type) {
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000103 error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " +
104 toString(Existing->getWasmType()) + " in " +
Sam Clegg3876d89a2018-05-14 22:42:33 +0000105 toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) +
106 " in " + toString(File));
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000107}
108
Sam Clegg1369dfa2018-06-21 00:12:25 +0000109static void checkFunctionType(Symbol *Existing, const InputFile *File,
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000110 const WasmSignature *NewSig) {
Sam Clegg65d63802018-05-14 23:01:16 +0000111 auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing);
112 if (!ExistingFunction) {
Sam Clegg3876d89a2018-05-14 22:42:33 +0000113 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000114 return;
115 }
116
Sam Clegg1369dfa2018-06-21 00:12:25 +0000117
Sam Clegg65d63802018-05-14 23:01:16 +0000118 const WasmSignature *OldSig = ExistingFunction->getFunctionType();
119 if (OldSig && NewSig && *NewSig != *OldSig) {
Sam Clegg1369dfa2018-06-21 00:12:25 +0000120 // Don't generate more than one warning per symbol.
121 if (Existing->SignatureMismatch)
122 return;
123 Existing->SignatureMismatch = true;
124
125 std::string msg = ("function signature mismatch: " + Existing->getName() +
126 "\n>>> defined as " + toString(*OldSig) + " in " +
127 toString(Existing->getFile()) + "\n>>> defined as " +
128 toString(*NewSig) + " in " + toString(File))
129 .str();
130 // A function signature mismatch is only really problem if the mismatched
131 // symbol is included in the final output, and gc-sections can remove the
132 // offending uses. Therefore we delay reporting this as an error when
133 // section GC is enabled.
134 if (Config->GcSections)
135 warn(msg);
136 else
137 error(msg);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000138 }
139}
140
Sam Cleggb8621592017-11-30 01:40:08 +0000141// Check the type of new symbol matches that of the symbol is replacing.
142// For functions this can also involve verifying that the signatures match.
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000143static void checkGlobalType(const Symbol *Existing, const InputFile *File,
144 const WasmGlobalType *NewType) {
145 if (!isa<GlobalSymbol>(Existing)) {
Sam Clegg3876d89a2018-05-14 22:42:33 +0000146 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL);
Sam Cleggb8621592017-11-30 01:40:08 +0000147 return;
148 }
149
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000150 const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType();
151 if (*NewType != *OldType) {
152 error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " +
153 toString(*OldType) + " in " + toString(Existing->getFile()) +
154 "\n>>> defined as " + toString(*NewType) + " in " + toString(File));
Sam Clegg93102972018-02-23 05:08:53 +0000155 }
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000156}
157
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000158static void checkDataType(const Symbol *Existing, const InputFile *File) {
159 if (!isa<DataSymbol>(Existing))
Sam Clegg3876d89a2018-05-14 22:42:33 +0000160 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000161}
162
Sam Cleggdfb0b2c2018-02-14 18:27:59 +0000163DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
Nicholas Wilsonebda41f2018-03-09 16:43:05 +0000164 uint32_t Flags,
165 InputFunction *Function) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000166 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
Rui Ueyamab961abc2018-02-28 22:51:51 +0000167 assert(!find(Name));
Nicholas Wilsonebda41f2018-03-09 16:43:05 +0000168 SyntheticFunctions.emplace_back(Function);
169 return replaceSymbol<DefinedFunction>(insert(Name).first, Name, Flags,
170 nullptr, Function);
Sam Clegg50686852018-01-12 18:35:13 +0000171}
172
Sam Clegg00245532018-02-20 23:38:27 +0000173DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,
174 uint32_t Flags) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000175 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n");
Rui Ueyamab961abc2018-02-28 22:51:51 +0000176 assert(!find(Name));
177 return replaceSymbol<DefinedData>(insert(Name).first, Name, Flags);
Sam Cleggc94d3932017-11-17 18:14:09 +0000178}
179
Sam Clegg93102972018-02-23 05:08:53 +0000180DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags,
181 InputGlobal *Global) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000182 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global
183 << "\n");
Rui Ueyamab961abc2018-02-28 22:51:51 +0000184 assert(!find(Name));
Nicholas Wilsonebda41f2018-03-09 16:43:05 +0000185 SyntheticGlobals.emplace_back(Global);
Rui Ueyamab961abc2018-02-28 22:51:51 +0000186 return replaceSymbol<DefinedGlobal>(insert(Name).first, Name, Flags, nullptr,
187 Global);
Sam Clegg93102972018-02-23 05:08:53 +0000188}
189
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000190static bool shouldReplace(const Symbol *Existing, InputFile *NewFile,
191 uint32_t NewFlags) {
Rui Ueyamac03c9042018-02-20 21:08:47 +0000192 // If existing symbol is undefined, replace it.
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000193 if (!Existing->isDefined()) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000194 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: "
195 << Existing->getName() << "\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000196 return true;
197 }
198
199 // Now we have two defined symbols. If the new one is weak, we can ignore it.
200 if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000201 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000202 return false;
203 }
204
205 // If the existing symbol is weak, we should replace it.
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000206 if (Existing->isWeak()) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000207 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000208 return true;
209 }
210
211 // Neither symbol is week. They conflict.
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000212 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
213 toString(Existing->getFile()) + "\n>>> defined in " +
214 toString(NewFile));
Rui Ueyamac03c9042018-02-20 21:08:47 +0000215 return true;
Sam Clegg93e559b2018-02-20 18:55:06 +0000216}
217
218Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000219 InputFile *File,
220 InputFunction *Function) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000221 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
Sam Clegg93e559b2018-02-20 18:55:06 +0000222 Symbol *S;
223 bool WasInserted;
224 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000225
Sam Cleggc729c1b2018-05-30 18:07:52 +0000226 if (!File || File->kind() == InputFile::ObjectKind)
227 S->IsUsedInRegularObj = true;
228
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000229 if (WasInserted || S->isLazy()) {
230 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);
231 return S;
232 }
233
Sam Cleggc729c1b2018-05-30 18:07:52 +0000234 if (Function)
235 checkFunctionType(S, File, &Function->Signature);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000236
237 if (shouldReplace(S, File, Flags))
238 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);
Sam Clegg93e559b2018-02-20 18:55:06 +0000239 return S;
240}
241
Sam Clegg00245532018-02-20 23:38:27 +0000242Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags,
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000243 InputFile *File, InputSegment *Segment,
Sam Clegg93102972018-02-23 05:08:53 +0000244 uint32_t Address, uint32_t Size) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000245 LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address
246 << "\n");
Sam Clegg93e559b2018-02-20 18:55:06 +0000247 Symbol *S;
248 bool WasInserted;
249 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000250
Sam Cleggc729c1b2018-05-30 18:07:52 +0000251 if (!File || File->kind() == InputFile::ObjectKind)
252 S->IsUsedInRegularObj = true;
253
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000254 if (WasInserted || S->isLazy()) {
255 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);
256 return S;
257 }
258
259 checkDataType(S, File);
260
261 if (shouldReplace(S, File, Flags))
262 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);
Sam Cleggc94d3932017-11-17 18:14:09 +0000263 return S;
264}
265
Sam Clegg93102972018-02-23 05:08:53 +0000266Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000267 InputFile *File, InputGlobal *Global) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000268 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n");
Sam Clegg93102972018-02-23 05:08:53 +0000269 Symbol *S;
270 bool WasInserted;
271 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000272
Sam Cleggc729c1b2018-05-30 18:07:52 +0000273 if (!File || File->kind() == InputFile::ObjectKind)
274 S->IsUsedInRegularObj = true;
275
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000276 if (WasInserted || S->isLazy()) {
277 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);
278 return S;
279 }
280
281 checkGlobalType(S, File, &Global->getType());
282
283 if (shouldReplace(S, File, Flags))
284 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);
Sam Clegg93102972018-02-23 05:08:53 +0000285 return S;
286}
287
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000288Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags,
289 InputFile *File,
290 const WasmSignature *Sig) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000291 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000292
Sam Cleggc94d3932017-11-17 18:14:09 +0000293 Symbol *S;
294 bool WasInserted;
Sam Clegg20db3812018-01-10 00:52:20 +0000295 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000296
Sam Cleggc729c1b2018-05-30 18:07:52 +0000297 if (!File || File->kind() == InputFile::ObjectKind)
298 S->IsUsedInRegularObj = true;
299
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000300 if (WasInserted)
301 replaceSymbol<UndefinedFunction>(S, Name, Flags, File, Sig);
302 else if (auto *Lazy = dyn_cast<LazySymbol>(S))
Rui Ueyamab961abc2018-02-28 22:51:51 +0000303 Lazy->fetch();
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000304 else if (S->isDefined())
305 checkFunctionType(S, File, Sig);
Sam Cleggc94d3932017-11-17 18:14:09 +0000306 return S;
307}
308
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000309Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags,
310 InputFile *File) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000311 LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n");
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000312
313 Symbol *S;
314 bool WasInserted;
315 std::tie(S, WasInserted) = insert(Name);
316
317 if (WasInserted)
318 replaceSymbol<UndefinedData>(S, Name, Flags, File);
319 else if (auto *Lazy = dyn_cast<LazySymbol>(S))
Rui Ueyamab961abc2018-02-28 22:51:51 +0000320 Lazy->fetch();
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000321 else if (S->isDefined())
322 checkDataType(S, File);
323 return S;
324}
325
326Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags,
327 InputFile *File,
328 const WasmGlobalType *Type) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000329 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n");
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000330
331 Symbol *S;
332 bool WasInserted;
333 std::tie(S, WasInserted) = insert(Name);
334
Sam Cleggc729c1b2018-05-30 18:07:52 +0000335 if (!File || File->kind() == InputFile::ObjectKind)
336 S->IsUsedInRegularObj = true;
337
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000338 if (WasInserted)
339 replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type);
340 else if (auto *Lazy = dyn_cast<LazySymbol>(S))
Rui Ueyamab961abc2018-02-28 22:51:51 +0000341 Lazy->fetch();
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000342 else if (S->isDefined())
343 checkGlobalType(S, File, Type);
344 return S;
345}
346
347void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000348 LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000349 StringRef Name = Sym->getName();
Rui Ueyamac03c9042018-02-20 21:08:47 +0000350
Sam Cleggc94d3932017-11-17 18:14:09 +0000351 Symbol *S;
352 bool WasInserted;
353 std::tie(S, WasInserted) = insert(Name);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000354
Sam Cleggc94d3932017-11-17 18:14:09 +0000355 if (WasInserted) {
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000356 replaceSymbol<LazySymbol>(S, Name, File, *Sym);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000357 return;
358 }
359
360 // If there is an existing undefined symbol, load a new one from the archive.
361 if (S->isUndefined()) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000362 LLVM_DEBUG(dbgs() << "replacing existing undefined\n");
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000363 File->addMember(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +0000364 }
365}
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000366
Nicholas Wilsonc4d9aa12018-03-14 15:45:11 +0000367bool SymbolTable::addComdat(StringRef Name) {
368 return Comdats.insert(CachedHashStringRef(Name)).second;
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000369}