blob: b61812523400049a0e58d47f9e1184895f52fa5b [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- SymbolTable.cpp ----------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Sam Cleggc94d3932017-11-17 18:14:09 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "SymbolTable.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000010#include "Config.h"
Sam Clegg5fa274b2018-01-10 01:13:34 +000011#include "InputChunks.h"
Heejin Ahne915a712018-12-08 06:17:43 +000012#include "InputEvent.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 Clegg45218f42018-11-27 01:08:16 +000023using namespace llvm::object;
Sam Cleggc94d3932017-11-17 18:14:09 +000024using namespace lld;
25using namespace lld::wasm;
26
Rui Ueyama136d27a2019-07-11 05:40:30 +000027SymbolTable *lld::wasm::symtab;
Sam Cleggc94d3932017-11-17 18:14:09 +000028
Rui Ueyama136d27a2019-07-11 05:40:30 +000029void SymbolTable::addFile(InputFile *file) {
30 log("Processing: " + toString(file));
Sam Clegga282a612019-06-05 17:50:45 +000031
32 // .a file
Rui Ueyama136d27a2019-07-11 05:40:30 +000033 if (auto *f = dyn_cast<ArchiveFile>(file)) {
34 f->parse();
Sam Clegga282a612019-06-05 17:50:45 +000035 return;
36 }
37
38 // .so file
Rui Ueyama136d27a2019-07-11 05:40:30 +000039 if (auto *f = dyn_cast<SharedFile>(file)) {
40 sharedFiles.push_back(f);
Sam Clegga282a612019-06-05 17:50:45 +000041 return;
42 }
43
Rui Ueyama136d27a2019-07-11 05:40:30 +000044 if (config->trace)
45 message(toString(file));
Sam Cleggc94d3932017-11-17 18:14:09 +000046
Sam Cleggc729c1b2018-05-30 18:07:52 +000047 // LLVM bitcode file
Rui Ueyama136d27a2019-07-11 05:40:30 +000048 if (auto *f = dyn_cast<BitcodeFile>(file)) {
49 f->parse();
50 bitcodeFiles.push_back(f);
Sam Clegga282a612019-06-05 17:50:45 +000051 return;
52 }
53
54 // Regular object file
Rui Ueyama136d27a2019-07-11 05:40:30 +000055 auto *f = cast<ObjFile>(file);
56 f->parse(false);
57 objectFiles.push_back(f);
Sam Cleggc94d3932017-11-17 18:14:09 +000058}
59
Sam Cleggc729c1b2018-05-30 18:07:52 +000060// This function is where all the optimizations of link-time
61// optimization happens. When LTO is in use, some input files are
62// not in native object file format but in the LLVM bitcode format.
63// This function compiles bitcode files into a few big native files
64// using LLVM functions and replaces bitcode symbols with the results.
65// Because all bitcode files that the program consists of are passed
66// to the compiler at once, it can do whole-program optimization.
67void SymbolTable::addCombinedLTOObject() {
Rui Ueyama136d27a2019-07-11 05:40:30 +000068 if (bitcodeFiles.empty())
Sam Cleggc729c1b2018-05-30 18:07:52 +000069 return;
70
71 // Compile bitcode files and replace bitcode symbols.
Rui Ueyama136d27a2019-07-11 05:40:30 +000072 lto.reset(new BitcodeCompiler);
73 for (BitcodeFile *f : bitcodeFiles)
74 lto->add(*f);
Sam Cleggc729c1b2018-05-30 18:07:52 +000075
Rui Ueyama136d27a2019-07-11 05:40:30 +000076 for (StringRef filename : lto->compile()) {
77 auto *obj = make<ObjFile>(MemoryBufferRef(filename, "lto.tmp"), "");
78 obj->parse(true);
79 objectFiles.push_back(obj);
Sam Cleggc729c1b2018-05-30 18:07:52 +000080 }
81}
82
Rui Ueyama136d27a2019-07-11 05:40:30 +000083Symbol *SymbolTable::find(StringRef name) {
84 auto it = symMap.find(CachedHashStringRef(name));
85 if (it == symMap.end() || it->second == -1)
Sam Clegg1f3f7742019-02-06 02:35:18 +000086 return nullptr;
Rui Ueyama136d27a2019-07-11 05:40:30 +000087 return symVector[it->second];
Sam Clegg1f3f7742019-02-06 02:35:18 +000088}
89
Rui Ueyama136d27a2019-07-11 05:40:30 +000090void SymbolTable::replace(StringRef name, Symbol* sym) {
91 auto it = symMap.find(CachedHashStringRef(name));
92 symVector[it->second] = sym;
Sam Clegg6540e572019-02-20 23:19:31 +000093}
94
Rui Ueyama136d27a2019-07-11 05:40:30 +000095std::pair<Symbol *, bool> SymbolTable::insertName(StringRef name) {
96 bool trace = false;
97 auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
98 int &symIndex = p.first->second;
99 bool isNew = p.second;
100 if (symIndex == -1) {
101 symIndex = symVector.size();
102 trace = true;
103 isNew = true;
Sam Clegg1f3f7742019-02-06 02:35:18 +0000104 }
105
Rui Ueyama136d27a2019-07-11 05:40:30 +0000106 if (!isNew)
107 return {symVector[symIndex], false};
Sam Clegg1f3f7742019-02-06 02:35:18 +0000108
Rui Ueyama136d27a2019-07-11 05:40:30 +0000109 Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
110 sym->isUsedInRegularObj = false;
111 sym->canInline = true;
112 sym->traced = trace;
113 symVector.emplace_back(sym);
114 return {sym, true};
Sam Cleggc94d3932017-11-17 18:14:09 +0000115}
116
Rui Ueyama136d27a2019-07-11 05:40:30 +0000117std::pair<Symbol *, bool> SymbolTable::insert(StringRef name,
118 const InputFile *file) {
119 Symbol *s;
120 bool wasInserted;
121 std::tie(s, wasInserted) = insertName(name);
Sam Clegg1f3f7742019-02-06 02:35:18 +0000122
Rui Ueyama136d27a2019-07-11 05:40:30 +0000123 if (!file || file->kind() == InputFile::ObjectKind)
124 s->isUsedInRegularObj = true;
Sam Clegg1f3f7742019-02-06 02:35:18 +0000125
Rui Ueyama136d27a2019-07-11 05:40:30 +0000126 return {s, wasInserted};
Sam Cleggc94d3932017-11-17 18:14:09 +0000127}
128
Rui Ueyama136d27a2019-07-11 05:40:30 +0000129static void reportTypeError(const Symbol *existing, const InputFile *file,
130 llvm::wasm::WasmSymbolType type) {
131 error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " +
132 toString(existing->getWasmType()) + " in " +
133 toString(existing->getFile()) + "\n>>> defined as " + toString(type) +
134 " in " + toString(file));
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000135}
136
Heejin Ahn6f4286f2018-11-19 23:31:28 +0000137// Check the type of new symbol matches that of the symbol is replacing.
Sam Clegg6540e572019-02-20 23:19:31 +0000138// Returns true if the function types match, false is there is a singature
139// mismatch.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000140static bool signatureMatches(FunctionSymbol *existing,
141 const WasmSignature *newSig) {
142 const WasmSignature *oldSig = existing->signature;
Sam Cleggd506b0a2019-05-29 15:36:42 +0000143
144 // If either function is missing a signature (this happend for bitcode
145 // symbols) then assume they match. Any mismatch will be reported later
146 // when the LTO objects are added.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000147 if (!newSig || !oldSig)
Sam Clegg6540e572019-02-20 23:19:31 +0000148 return true;
Sam Cleggcefbf9a2018-06-28 16:53:53 +0000149
Rui Ueyama136d27a2019-07-11 05:40:30 +0000150 return *newSig == *oldSig;
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000151}
152
Rui Ueyama136d27a2019-07-11 05:40:30 +0000153static void checkGlobalType(const Symbol *existing, const InputFile *file,
154 const WasmGlobalType *newType) {
155 if (!isa<GlobalSymbol>(existing)) {
156 reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL);
Sam Cleggb8621592017-11-30 01:40:08 +0000157 return;
158 }
159
Rui Ueyama136d27a2019-07-11 05:40:30 +0000160 const WasmGlobalType *oldType = cast<GlobalSymbol>(existing)->getGlobalType();
161 if (*newType != *oldType) {
162 error("Global type mismatch: " + existing->getName() + "\n>>> defined as " +
163 toString(*oldType) + " in " + toString(existing->getFile()) +
164 "\n>>> defined as " + toString(*newType) + " in " + toString(file));
Sam Clegg93102972018-02-23 05:08:53 +0000165 }
Sam Clegg24b3dcd2018-01-28 19:57:01 +0000166}
167
Rui Ueyama136d27a2019-07-11 05:40:30 +0000168static void checkEventType(const Symbol *existing, const InputFile *file,
169 const WasmEventType *newType,
170 const WasmSignature *newSig) {
171 auto existingEvent = dyn_cast<EventSymbol>(existing);
172 if (!isa<EventSymbol>(existing)) {
173 reportTypeError(existing, file, WASM_SYMBOL_TYPE_EVENT);
Heejin Ahne915a712018-12-08 06:17:43 +0000174 return;
175 }
176
Rui Ueyama136d27a2019-07-11 05:40:30 +0000177 const WasmEventType *oldType = cast<EventSymbol>(existing)->getEventType();
178 const WasmSignature *oldSig = existingEvent->signature;
179 if (newType->Attribute != oldType->Attribute)
180 error("Event type mismatch: " + existing->getName() + "\n>>> defined as " +
181 toString(*oldType) + " in " + toString(existing->getFile()) +
182 "\n>>> defined as " + toString(*newType) + " in " + toString(file));
183 if (*newSig != *oldSig)
184 warn("Event signature mismatch: " + existing->getName() +
185 "\n>>> defined as " + toString(*oldSig) + " in " +
186 toString(existing->getFile()) + "\n>>> defined as " +
187 toString(*newSig) + " in " + toString(file));
Heejin Ahne915a712018-12-08 06:17:43 +0000188}
189
Rui Ueyama136d27a2019-07-11 05:40:30 +0000190static void checkDataType(const Symbol *existing, const InputFile *file) {
191 if (!isa<DataSymbol>(existing))
192 reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000193}
194
Rui Ueyama136d27a2019-07-11 05:40:30 +0000195DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name,
196 uint32_t flags,
197 InputFunction *function) {
198 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << name << "\n");
199 assert(!find(name));
200 syntheticFunctions.emplace_back(function);
201 return replaceSymbol<DefinedFunction>(insertName(name).first, name,
202 flags, nullptr, function);
Sam Clegg50686852018-01-12 18:35:13 +0000203}
204
Sam Clegg8e8ddaa2019-06-04 16:35:23 +0000205// Adds an optional, linker generated, data symbols. The symbol will only be
206// added if there is an undefine reference to it, or if it is explictly exported
207// via the --export flag. Otherwise we don't add the symbol and return nullptr.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000208DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name, uint32_t value,
209 uint32_t flags) {
210 Symbol *s = find(name);
211 if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0))
212 s = insertName(name).first;
213 else if (!s || s->isDefined())
Sam Clegg4bce63a2019-05-23 10:06:03 +0000214 return nullptr;
Rui Ueyama136d27a2019-07-11 05:40:30 +0000215 LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n");
216 auto *rtn = replaceSymbol<DefinedData>(s, name, flags);
217 rtn->setVirtualAddress(value);
218 rtn->referenced = true;
Sam Clegg4bce63a2019-05-23 10:06:03 +0000219 return rtn;
220}
221
Rui Ueyama136d27a2019-07-11 05:40:30 +0000222DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name,
223 uint32_t flags) {
224 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n");
225 assert(!find(name));
226 return replaceSymbol<DefinedData>(insertName(name).first, name, flags);
Sam Cleggc94d3932017-11-17 18:14:09 +0000227}
228
Rui Ueyama136d27a2019-07-11 05:40:30 +0000229DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags,
230 InputGlobal *global) {
231 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << name << " -> " << global
Nicola Zaghene7245b42018-05-15 13:36:20 +0000232 << "\n");
Rui Ueyama136d27a2019-07-11 05:40:30 +0000233 assert(!find(name));
234 syntheticGlobals.emplace_back(global);
235 return replaceSymbol<DefinedGlobal>(insertName(name).first, name, flags,
236 nullptr, global);
Sam Clegg93102972018-02-23 05:08:53 +0000237}
238
Rui Ueyama136d27a2019-07-11 05:40:30 +0000239static bool shouldReplace(const Symbol *existing, InputFile *newFile,
240 uint32_t newFlags) {
Rui Ueyamac03c9042018-02-20 21:08:47 +0000241 // If existing symbol is undefined, replace it.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000242 if (!existing->isDefined()) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000243 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: "
Rui Ueyama136d27a2019-07-11 05:40:30 +0000244 << existing->getName() << "\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000245 return true;
246 }
247
248 // Now we have two defined symbols. If the new one is weak, we can ignore it.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000249 if ((newFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000250 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000251 return false;
252 }
253
254 // If the existing symbol is weak, we should replace it.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000255 if (existing->isWeak()) {
Nicola Zaghene7245b42018-05-15 13:36:20 +0000256 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000257 return true;
258 }
259
260 // Neither symbol is week. They conflict.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000261 error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " +
262 toString(existing->getFile()) + "\n>>> defined in " +
263 toString(newFile));
Rui Ueyamac03c9042018-02-20 21:08:47 +0000264 return true;
Sam Clegg93e559b2018-02-20 18:55:06 +0000265}
266
Rui Ueyama136d27a2019-07-11 05:40:30 +0000267Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags,
268 InputFile *file,
269 InputFunction *function) {
270 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << name << " ["
271 << (function ? toString(function->signature) : "none")
Sam Clegg8b0b48f2018-09-28 16:50:14 +0000272 << "]\n");
Rui Ueyama136d27a2019-07-11 05:40:30 +0000273 Symbol *s;
274 bool wasInserted;
275 std::tie(s, wasInserted) = insert(name, file);
Sam Cleggc729c1b2018-05-30 18:07:52 +0000276
Rui Ueyama136d27a2019-07-11 05:40:30 +0000277 auto replaceSym = [&](Symbol *sym) {
Sam Clegg6540e572019-02-20 23:19:31 +0000278 // If the new defined function doesn't have signture (i.e. bitcode
279 // functions) but the old symbol does, then preserve the old signature
Rui Ueyama136d27a2019-07-11 05:40:30 +0000280 const WasmSignature *oldSig = s->getSignature();
281 auto* newSym = replaceSymbol<DefinedFunction>(sym, name, flags, file, function);
282 if (!newSym->signature)
283 newSym->signature = oldSig;
Sam Clegg6540e572019-02-20 23:19:31 +0000284 };
285
Rui Ueyama136d27a2019-07-11 05:40:30 +0000286 if (wasInserted || s->isLazy()) {
287 replaceSym(s);
288 return s;
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000289 }
290
Rui Ueyama136d27a2019-07-11 05:40:30 +0000291 auto existingFunction = dyn_cast<FunctionSymbol>(s);
292 if (!existingFunction) {
293 reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
294 return s;
Sam Clegg8b0b48f2018-09-28 16:50:14 +0000295 }
Sam Clegg6540e572019-02-20 23:19:31 +0000296
Rui Ueyama136d27a2019-07-11 05:40:30 +0000297 bool checkSig = true;
298 if (auto ud = dyn_cast<UndefinedFunction>(existingFunction))
299 checkSig = ud->isCalledDirectly;
Sam Clegg59f959f2019-05-24 22:45:08 +0000300
Rui Ueyama136d27a2019-07-11 05:40:30 +0000301 if (checkSig && function && !signatureMatches(existingFunction, &function->signature)) {
302 Symbol* variant;
303 if (getFunctionVariant(s, &function->signature, file, &variant))
Sam Clegg6540e572019-02-20 23:19:31 +0000304 // New variant, always replace
Rui Ueyama136d27a2019-07-11 05:40:30 +0000305 replaceSym(variant);
306 else if (shouldReplace(s, file, flags))
Sam Clegg6540e572019-02-20 23:19:31 +0000307 // Variant already exists, replace it after checking shouldReplace
Rui Ueyama136d27a2019-07-11 05:40:30 +0000308 replaceSym(variant);
Sam Clegg6540e572019-02-20 23:19:31 +0000309
310 // This variant we found take the place in the symbol table as the primary
311 // variant.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000312 replace(name, variant);
313 return variant;
Sam Clegg6540e572019-02-20 23:19:31 +0000314 }
315
316 // Existing function with matching signature.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000317 if (shouldReplace(s, file, flags))
318 replaceSym(s);
Sam Clegg6540e572019-02-20 23:19:31 +0000319
Rui Ueyama136d27a2019-07-11 05:40:30 +0000320 return s;
Sam Clegg93e559b2018-02-20 18:55:06 +0000321}
322
Rui Ueyama136d27a2019-07-11 05:40:30 +0000323Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags,
324 InputFile *file, InputSegment *segment,
325 uint32_t address, uint32_t size) {
326 LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address
Nicola Zaghene7245b42018-05-15 13:36:20 +0000327 << "\n");
Rui Ueyama136d27a2019-07-11 05:40:30 +0000328 Symbol *s;
329 bool wasInserted;
330 std::tie(s, wasInserted) = insert(name, file);
Sam Cleggc729c1b2018-05-30 18:07:52 +0000331
Rui Ueyama136d27a2019-07-11 05:40:30 +0000332 auto replaceSym = [&]() {
333 replaceSymbol<DefinedData>(s, name, flags, file, segment, address, size);
Sam Clegg6540e572019-02-20 23:19:31 +0000334 };
335
Rui Ueyama136d27a2019-07-11 05:40:30 +0000336 if (wasInserted || s->isLazy()) {
337 replaceSym();
338 return s;
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000339 }
340
Rui Ueyama136d27a2019-07-11 05:40:30 +0000341 checkDataType(s, file);
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000342
Rui Ueyama136d27a2019-07-11 05:40:30 +0000343 if (shouldReplace(s, file, flags))
344 replaceSym();
345 return s;
Sam Cleggc94d3932017-11-17 18:14:09 +0000346}
347
Rui Ueyama136d27a2019-07-11 05:40:30 +0000348Symbol *SymbolTable::addDefinedGlobal(StringRef name, uint32_t flags,
349 InputFile *file, InputGlobal *global) {
350 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << name << "\n");
Sam Clegg4c2cbfe2018-08-02 20:39:19 +0000351
Rui Ueyama136d27a2019-07-11 05:40:30 +0000352 Symbol *s;
353 bool wasInserted;
354 std::tie(s, wasInserted) = insert(name, file);
Sam Cleggc729c1b2018-05-30 18:07:52 +0000355
Rui Ueyama136d27a2019-07-11 05:40:30 +0000356 auto replaceSym = [&]() {
357 replaceSymbol<DefinedGlobal>(s, name, flags, file, global);
Sam Clegg6540e572019-02-20 23:19:31 +0000358 };
359
Rui Ueyama136d27a2019-07-11 05:40:30 +0000360 if (wasInserted || s->isLazy()) {
361 replaceSym();
362 return s;
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000363 }
364
Rui Ueyama136d27a2019-07-11 05:40:30 +0000365 checkGlobalType(s, file, &global->getType());
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000366
Rui Ueyama136d27a2019-07-11 05:40:30 +0000367 if (shouldReplace(s, file, flags))
368 replaceSym();
369 return s;
Sam Clegg93102972018-02-23 05:08:53 +0000370}
371
Rui Ueyama136d27a2019-07-11 05:40:30 +0000372Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags,
373 InputFile *file, InputEvent *event) {
374 LLVM_DEBUG(dbgs() << "addDefinedEvent:" << name << "\n");
Heejin Ahne915a712018-12-08 06:17:43 +0000375
Rui Ueyama136d27a2019-07-11 05:40:30 +0000376 Symbol *s;
377 bool wasInserted;
378 std::tie(s, wasInserted) = insert(name, file);
Heejin Ahne915a712018-12-08 06:17:43 +0000379
Rui Ueyama136d27a2019-07-11 05:40:30 +0000380 auto replaceSym = [&]() {
381 replaceSymbol<DefinedEvent>(s, name, flags, file, event);
Sam Clegg6540e572019-02-20 23:19:31 +0000382 };
383
Rui Ueyama136d27a2019-07-11 05:40:30 +0000384 if (wasInserted || s->isLazy()) {
385 replaceSym();
386 return s;
Heejin Ahne915a712018-12-08 06:17:43 +0000387 }
388
Rui Ueyama136d27a2019-07-11 05:40:30 +0000389 checkEventType(s, file, &event->getType(), &event->signature);
Heejin Ahne915a712018-12-08 06:17:43 +0000390
Rui Ueyama136d27a2019-07-11 05:40:30 +0000391 if (shouldReplace(s, file, flags))
392 replaceSym();
393 return s;
Heejin Ahne915a712018-12-08 06:17:43 +0000394}
395
Rui Ueyama136d27a2019-07-11 05:40:30 +0000396Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName,
397 StringRef importModule,
398 uint32_t flags, InputFile *file,
399 const WasmSignature *sig,
400 bool isCalledDirectly) {
401 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << name << " ["
402 << (sig ? toString(*sig) : "none")
403 << "] IsCalledDirectly:" << isCalledDirectly << "\n");
Rui Ueyamac03c9042018-02-20 21:08:47 +0000404
Rui Ueyama136d27a2019-07-11 05:40:30 +0000405 Symbol *s;
406 bool wasInserted;
407 std::tie(s, wasInserted) = insert(name, file);
408 if (s->traced)
409 printTraceSymbolUndefined(name, file);
Sam Cleggc729c1b2018-05-30 18:07:52 +0000410
Rui Ueyama136d27a2019-07-11 05:40:30 +0000411 auto replaceSym = [&]() {
412 replaceSymbol<UndefinedFunction>(s, name, importName, importModule, flags,
413 file, sig, isCalledDirectly);
Sam Clegg6540e572019-02-20 23:19:31 +0000414 };
415
Rui Ueyama136d27a2019-07-11 05:40:30 +0000416 if (wasInserted)
417 replaceSym();
418 else if (auto *lazy = dyn_cast<LazySymbol>(s))
419 lazy->fetch();
Sam Clegg6540e572019-02-20 23:19:31 +0000420 else {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000421 auto existingFunction = dyn_cast<FunctionSymbol>(s);
422 if (!existingFunction) {
423 reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
424 return s;
Sam Clegg6540e572019-02-20 23:19:31 +0000425 }
Rui Ueyama136d27a2019-07-11 05:40:30 +0000426 if (!existingFunction->signature && sig)
427 existingFunction->signature = sig;
428 if (isCalledDirectly && !signatureMatches(existingFunction, sig))
429 if (getFunctionVariant(s, sig, file, &s))
430 replaceSym();
Sam Clegg6540e572019-02-20 23:19:31 +0000431 }
Sam Cleggcefbf9a2018-06-28 16:53:53 +0000432
Rui Ueyama136d27a2019-07-11 05:40:30 +0000433 return s;
Sam Cleggc94d3932017-11-17 18:14:09 +0000434}
435
Rui Ueyama136d27a2019-07-11 05:40:30 +0000436Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags,
437 InputFile *file) {
438 LLVM_DEBUG(dbgs() << "addUndefinedData: " << name << "\n");
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000439
Rui Ueyama136d27a2019-07-11 05:40:30 +0000440 Symbol *s;
441 bool wasInserted;
442 std::tie(s, wasInserted) = insert(name, file);
443 if (s->traced)
444 printTraceSymbolUndefined(name, file);
Sam Cleggf989a922018-07-17 19:15:02 +0000445
Rui Ueyama136d27a2019-07-11 05:40:30 +0000446 if (wasInserted)
447 replaceSymbol<UndefinedData>(s, name, flags, file);
448 else if (auto *lazy = dyn_cast<LazySymbol>(s))
449 lazy->fetch();
450 else if (s->isDefined())
451 checkDataType(s, file);
452 return s;
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000453}
454
Rui Ueyama136d27a2019-07-11 05:40:30 +0000455Symbol *SymbolTable::addUndefinedGlobal(StringRef name, StringRef importName,
456 StringRef importModule, uint32_t flags,
457 InputFile *file,
458 const WasmGlobalType *type) {
459 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n");
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000460
Rui Ueyama136d27a2019-07-11 05:40:30 +0000461 Symbol *s;
462 bool wasInserted;
463 std::tie(s, wasInserted) = insert(name, file);
464 if (s->traced)
465 printTraceSymbolUndefined(name, file);
Sam Cleggc729c1b2018-05-30 18:07:52 +0000466
Rui Ueyama136d27a2019-07-11 05:40:30 +0000467 if (wasInserted)
468 replaceSymbol<UndefinedGlobal>(s, name, importName, importModule, flags,
469 file, type);
470 else if (auto *lazy = dyn_cast<LazySymbol>(s))
471 lazy->fetch();
472 else if (s->isDefined())
473 checkGlobalType(s, file, type);
474 return s;
Rui Ueyamae3498ec2018-02-28 00:09:22 +0000475}
476
Rui Ueyama136d27a2019-07-11 05:40:30 +0000477void SymbolTable::addLazy(ArchiveFile *file, const Archive::Symbol *sym) {
478 LLVM_DEBUG(dbgs() << "addLazy: " << sym->getName() << "\n");
479 StringRef name = sym->getName();
Rui Ueyamac03c9042018-02-20 21:08:47 +0000480
Rui Ueyama136d27a2019-07-11 05:40:30 +0000481 Symbol *s;
482 bool wasInserted;
483 std::tie(s, wasInserted) = insertName(name);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000484
Rui Ueyama136d27a2019-07-11 05:40:30 +0000485 if (wasInserted) {
486 replaceSymbol<LazySymbol>(s, name, 0, file, *sym);
Rui Ueyamac03c9042018-02-20 21:08:47 +0000487 return;
488 }
489
Rui Ueyama136d27a2019-07-11 05:40:30 +0000490 if (!s->isUndefined())
Sam Clegg37b4ee52019-01-29 22:26:31 +0000491 return;
492
493 // The existing symbol is undefined, load a new one from the archive,
494 // unless the the existing symbol is weak in which case replace the undefined
495 // symbols with a LazySymbol.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000496 if (s->isWeak()) {
497 const WasmSignature *oldSig = nullptr;
Sam Clegg37b4ee52019-01-29 22:26:31 +0000498 // In the case of an UndefinedFunction we need to preserve the expected
499 // signature.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000500 if (auto *f = dyn_cast<UndefinedFunction>(s))
501 oldSig = f->signature;
Sam Clegg37b4ee52019-01-29 22:26:31 +0000502 LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n");
Rui Ueyama136d27a2019-07-11 05:40:30 +0000503 auto newSym = replaceSymbol<LazySymbol>(s, name, WASM_SYMBOL_BINDING_WEAK,
504 file, *sym);
505 newSym->signature = oldSig;
Sam Clegg37b4ee52019-01-29 22:26:31 +0000506 return;
Sam Cleggc94d3932017-11-17 18:14:09 +0000507 }
Sam Clegg37b4ee52019-01-29 22:26:31 +0000508
509 LLVM_DEBUG(dbgs() << "replacing existing undefined\n");
Rui Ueyama136d27a2019-07-11 05:40:30 +0000510 file->addMember(sym);
Sam Cleggc94d3932017-11-17 18:14:09 +0000511}
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000512
Rui Ueyama136d27a2019-07-11 05:40:30 +0000513bool SymbolTable::addComdat(StringRef name) {
514 return comdatGroups.insert(CachedHashStringRef(name)).second;
Sam Clegge0f6fcd2018-01-12 22:25:17 +0000515}
Sam Clegg1f3f7742019-02-06 02:35:18 +0000516
Sam Clegg6540e572019-02-20 23:19:31 +0000517// The new signature doesn't match. Create a variant to the symbol with the
518// signature encoded in the name and return that instead. These symbols are
519// then unified later in handleSymbolVariants.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000520bool SymbolTable::getFunctionVariant(Symbol* sym, const WasmSignature *sig,
521 const InputFile *file, Symbol **out) {
522 LLVM_DEBUG(dbgs() << "getFunctionVariant: " << sym->getName() << " -> "
523 << " " << toString(*sig) << "\n");
524 Symbol *variant = nullptr;
Sam Clegg6540e572019-02-20 23:19:31 +0000525
526 // Linear search through symbol variants. Should never be more than two
527 // or three entries here.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000528 auto &variants = symVariants[CachedHashStringRef(sym->getName())];
529 if (variants.empty())
530 variants.push_back(sym);
Sam Clegg6540e572019-02-20 23:19:31 +0000531
Rui Ueyama136d27a2019-07-11 05:40:30 +0000532 for (Symbol* v : variants) {
533 if (*v->getSignature() == *sig) {
534 variant = v;
Sam Clegg6540e572019-02-20 23:19:31 +0000535 break;
536 }
537 }
538
Rui Ueyama136d27a2019-07-11 05:40:30 +0000539 bool wasAdded = !variant;
540 if (wasAdded) {
Sam Clegg6540e572019-02-20 23:19:31 +0000541 // Create a new variant;
542 LLVM_DEBUG(dbgs() << "added new variant\n");
Rui Ueyama136d27a2019-07-11 05:40:30 +0000543 variant = reinterpret_cast<Symbol *>(make<SymbolUnion>());
544 variants.push_back(variant);
Sam Clegg6540e572019-02-20 23:19:31 +0000545 } else {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000546 LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*variant) << "\n");
547 assert(*variant->getSignature() == *sig);
Sam Clegg6540e572019-02-20 23:19:31 +0000548 }
549
Rui Ueyama136d27a2019-07-11 05:40:30 +0000550 *out = variant;
551 return wasAdded;
Sam Clegg6540e572019-02-20 23:19:31 +0000552}
553
Sam Clegg1f3f7742019-02-06 02:35:18 +0000554// Set a flag for --trace-symbol so that we can print out a log message
555// if a new symbol with the same name is inserted into the symbol table.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000556void SymbolTable::trace(StringRef name) {
557 symMap.insert({CachedHashStringRef(name), -1});
Sam Clegg1f3f7742019-02-06 02:35:18 +0000558}
Sam Clegg230dc112019-02-07 22:42:16 +0000559
Rui Ueyama136d27a2019-07-11 05:40:30 +0000560void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
Sam Clegga5ca34e2019-05-24 14:14:25 +0000561 // Swap symbols as instructed by -wrap.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000562 int &origIdx = symMap[CachedHashStringRef(sym->getName())];
563 int &realIdx= symMap[CachedHashStringRef(real->getName())];
564 int &wrapIdx = symMap[CachedHashStringRef(wrap->getName())];
565 LLVM_DEBUG(dbgs() << "wrap: " << sym->getName() << "\n");
Sam Clegga5ca34e2019-05-24 14:14:25 +0000566
567 // Anyone looking up __real symbols should get the original
Rui Ueyama136d27a2019-07-11 05:40:30 +0000568 realIdx = origIdx;
Sam Clegga5ca34e2019-05-24 14:14:25 +0000569 // Anyone looking up the original should get the __wrap symbol
Rui Ueyama136d27a2019-07-11 05:40:30 +0000570 origIdx = wrapIdx;
Sam Clegga5ca34e2019-05-24 14:14:25 +0000571}
572
Rui Ueyama136d27a2019-07-11 05:40:30 +0000573static const uint8_t unreachableFn[] = {
Sam Clegg230dc112019-02-07 22:42:16 +0000574 0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
575 0x00 /* opcode unreachable */, 0x0b /* opcode end */
576};
577
578// Replace the given symbol body with an unreachable function.
579// This is used by handleWeakUndefines in order to generate a callable
Sam Clegg6540e572019-02-20 23:19:31 +0000580// equivalent of an undefined function and also handleSymbolVariants for
581// undefined functions that don't match the signature of the definition.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000582InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym,
583 const WasmSignature &sig,
584 StringRef debugName) {
585 auto *func = make<SyntheticFunction>(sig, sym->getName(), debugName);
586 func->setBody(unreachableFn);
587 syntheticFunctions.emplace_back(func);
588 replaceSymbol<DefinedFunction>(sym, sym->getName(), sym->getFlags(), nullptr,
589 func);
590 return func;
Sam Clegg230dc112019-02-07 22:42:16 +0000591}
592
593// For weak undefined functions, there may be "call" instructions that reference
594// the symbol. In this case, we need to synthesise a dummy/stub function that
595// will abort at runtime, so that relocations can still provided an operand to
596// the call instruction that passes Wasm validation.
597void SymbolTable::handleWeakUndefines() {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000598 for (Symbol *sym : getSymbols()) {
599 if (!sym->isUndefWeak())
Sam Clegg230dc112019-02-07 22:42:16 +0000600 continue;
601
Rui Ueyama136d27a2019-07-11 05:40:30 +0000602 const WasmSignature *sig = sym->getSignature();
603 if (!sig) {
Sam Clegg230dc112019-02-07 22:42:16 +0000604 // It is possible for undefined functions not to have a signature (eg. if
605 // added via "--undefined"), but weak undefined ones do have a signature.
Sam Clegg6540e572019-02-20 23:19:31 +0000606 // Lazy symbols may not be functions and therefore Sig can still be null
607 // in some circumstantce.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000608 assert(!isa<FunctionSymbol>(sym));
Sam Clegg230dc112019-02-07 22:42:16 +0000609 continue;
Sam Clegg6540e572019-02-20 23:19:31 +0000610 }
Sam Clegg230dc112019-02-07 22:42:16 +0000611
612 // Add a synthetic dummy for weak undefined functions. These dummies will
613 // be GC'd if not used as the target of any "call" instructions.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000614 StringRef debugName = saver.save("undefined:" + toString(*sym));
615 InputFunction* func = replaceWithUnreachable(sym, *sig, debugName);
Sam Clegg230dc112019-02-07 22:42:16 +0000616 // Ensure it compares equal to the null pointer, and so that table relocs
617 // don't pull in the stub body (only call-operand relocs should do that).
Rui Ueyama136d27a2019-07-11 05:40:30 +0000618 func->setTableIndex(0);
Sam Clegg230dc112019-02-07 22:42:16 +0000619 // Hide our dummy to prevent export.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000620 sym->setHidden(true);
Sam Clegg230dc112019-02-07 22:42:16 +0000621 }
622}
Sam Clegg6540e572019-02-20 23:19:31 +0000623
Rui Ueyama136d27a2019-07-11 05:40:30 +0000624static void reportFunctionSignatureMismatch(StringRef symName,
625 FunctionSymbol *a,
626 FunctionSymbol *b, bool isError) {
627 std::string msg = ("function signature mismatch: " + symName +
628 "\n>>> defined as " + toString(*a->signature) + " in " +
629 toString(a->getFile()) + "\n>>> defined as " +
630 toString(*b->signature) + " in " + toString(b->getFile()))
Sam Clegg6540e572019-02-20 23:19:31 +0000631 .str();
Rui Ueyama136d27a2019-07-11 05:40:30 +0000632 if (isError)
Sam Clegg6540e572019-02-20 23:19:31 +0000633 error(msg);
634 else
635 warn(msg);
636}
637
638// Remove any variant symbols that were created due to function signature
639// mismatches.
640void SymbolTable::handleSymbolVariants() {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000641 for (auto pair : symVariants) {
Sam Clegg6540e572019-02-20 23:19:31 +0000642 // Push the initial symbol onto the list of variants.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000643 StringRef symName = pair.first.val();
644 std::vector<Symbol *> &variants = pair.second;
Sam Clegg6540e572019-02-20 23:19:31 +0000645
646#ifndef NDEBUG
Rui Ueyama136d27a2019-07-11 05:40:30 +0000647 LLVM_DEBUG(dbgs() << "symbol with (" << variants.size()
648 << ") variants: " << symName << "\n");
649 for (auto *s: variants) {
650 auto *f = cast<FunctionSymbol>(s);
651 LLVM_DEBUG(dbgs() << " variant: " + f->getName() << " "
652 << toString(*f->signature) << "\n");
Sam Clegg6540e572019-02-20 23:19:31 +0000653 }
654#endif
655
656 // Find the one definition.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000657 DefinedFunction *defined = nullptr;
658 for (auto *symbol : variants) {
659 if (auto f = dyn_cast<DefinedFunction>(symbol)) {
660 defined = f;
Sam Clegg6540e572019-02-20 23:19:31 +0000661 break;
662 }
663 }
664
665 // If there are no definitions, and the undefined symbols disagree on
666 // the signature, there is not we can do since we don't know which one
667 // to use as the signature on the import.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000668 if (!defined) {
669 reportFunctionSignatureMismatch(symName,
670 cast<FunctionSymbol>(variants[0]),
671 cast<FunctionSymbol>(variants[1]), true);
Sam Clegg6540e572019-02-20 23:19:31 +0000672 return;
673 }
674
Rui Ueyama136d27a2019-07-11 05:40:30 +0000675 for (auto *symbol : variants) {
676 if (symbol != defined) {
677 auto *f = cast<FunctionSymbol>(symbol);
678 reportFunctionSignatureMismatch(symName, f, defined, false);
679 StringRef debugName = saver.save("unreachable:" + toString(*f));
680 replaceWithUnreachable(f, *f->signature, debugName);
Sam Clegg6540e572019-02-20 23:19:31 +0000681 }
682 }
683 }
684}