1 //===- SymbolTable.cpp ----------------------------------------------------===// 2 // 3 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "SymbolTable.h" 10 #include "Config.h" 11 #include "InputChunks.h" 12 #include "InputElement.h" 13 #include "WriterUtils.h" 14 #include "lld/Common/ErrorHandler.h" 15 #include "lld/Common/Memory.h" 16 #include "llvm/ADT/SetVector.h" 17 18 #define DEBUG_TYPE "lld" 19 20 using namespace llvm; 21 using namespace llvm::wasm; 22 using namespace llvm::object; 23 24 namespace lld { 25 namespace wasm { 26 SymbolTable *symtab; 27 28 void SymbolTable::addFile(InputFile *file) { 29 log("Processing: " + toString(file)); 30 31 // .a file 32 if (auto *f = dyn_cast<ArchiveFile>(file)) { 33 f->parse(); 34 return; 35 } 36 37 // .so file 38 if (auto *f = dyn_cast<SharedFile>(file)) { 39 sharedFiles.push_back(f); 40 return; 41 } 42 43 if (config->trace) 44 message(toString(file)); 45 46 // LLVM bitcode file 47 if (auto *f = dyn_cast<BitcodeFile>(file)) { 48 f->parse(); 49 bitcodeFiles.push_back(f); 50 return; 51 } 52 53 // Regular object file 54 auto *f = cast<ObjFile>(file); 55 f->parse(false); 56 objectFiles.push_back(f); 57 } 58 59 // This function is where all the optimizations of link-time 60 // optimization happens. When LTO is in use, some input files are 61 // not in native object file format but in the LLVM bitcode format. 62 // This function compiles bitcode files into a few big native files 63 // using LLVM functions and replaces bitcode symbols with the results. 64 // Because all bitcode files that the program consists of are passed 65 // to the compiler at once, it can do whole-program optimization. 66 void SymbolTable::addCombinedLTOObject() { 67 // Prevent further LTO objects being included 68 BitcodeFile::doneLTO = true; 69 70 if (bitcodeFiles.empty()) 71 return; 72 73 // Compile bitcode files and replace bitcode symbols. 74 lto.reset(new BitcodeCompiler); 75 for (BitcodeFile *f : bitcodeFiles) 76 lto->add(*f); 77 78 for (StringRef filename : lto->compile()) { 79 auto *obj = make<ObjFile>(MemoryBufferRef(filename, "lto.tmp"), ""); 80 obj->parse(true); 81 objectFiles.push_back(obj); 82 } 83 } 84 85 Symbol *SymbolTable::find(StringRef name) { 86 auto it = symMap.find(CachedHashStringRef(name)); 87 if (it == symMap.end() || it->second == -1) 88 return nullptr; 89 return symVector[it->second]; 90 } 91 92 void SymbolTable::replace(StringRef name, Symbol* sym) { 93 auto it = symMap.find(CachedHashStringRef(name)); 94 symVector[it->second] = sym; 95 } 96 97 std::pair<Symbol *, bool> SymbolTable::insertName(StringRef name) { 98 bool trace = false; 99 auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); 100 int &symIndex = p.first->second; 101 bool isNew = p.second; 102 if (symIndex == -1) { 103 symIndex = symVector.size(); 104 trace = true; 105 isNew = true; 106 } 107 108 if (!isNew) 109 return {symVector[symIndex], false}; 110 111 Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 112 sym->isUsedInRegularObj = false; 113 sym->canInline = true; 114 sym->traced = trace; 115 sym->forceExport = false; 116 symVector.emplace_back(sym); 117 return {sym, true}; 118 } 119 120 std::pair<Symbol *, bool> SymbolTable::insert(StringRef name, 121 const InputFile *file) { 122 Symbol *s; 123 bool wasInserted; 124 std::tie(s, wasInserted) = insertName(name); 125 126 if (!file || file->kind() == InputFile::ObjectKind) 127 s->isUsedInRegularObj = true; 128 129 return {s, wasInserted}; 130 } 131 132 static void reportTypeError(const Symbol *existing, const InputFile *file, 133 llvm::wasm::WasmSymbolType type) { 134 error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " + 135 toString(existing->getWasmType()) + " in " + 136 toString(existing->getFile()) + "\n>>> defined as " + toString(type) + 137 " in " + toString(file)); 138 } 139 140 // Check the type of new symbol matches that of the symbol is replacing. 141 // Returns true if the function types match, false is there is a signature 142 // mismatch. 143 static bool signatureMatches(FunctionSymbol *existing, 144 const WasmSignature *newSig) { 145 const WasmSignature *oldSig = existing->signature; 146 147 // If either function is missing a signature (this happend for bitcode 148 // symbols) then assume they match. Any mismatch will be reported later 149 // when the LTO objects are added. 150 if (!newSig || !oldSig) 151 return true; 152 153 return *newSig == *oldSig; 154 } 155 156 static void checkGlobalType(const Symbol *existing, const InputFile *file, 157 const WasmGlobalType *newType) { 158 if (!isa<GlobalSymbol>(existing)) { 159 reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL); 160 return; 161 } 162 163 const WasmGlobalType *oldType = cast<GlobalSymbol>(existing)->getGlobalType(); 164 if (*newType != *oldType) { 165 error("Global type mismatch: " + existing->getName() + "\n>>> defined as " + 166 toString(*oldType) + " in " + toString(existing->getFile()) + 167 "\n>>> defined as " + toString(*newType) + " in " + toString(file)); 168 } 169 } 170 171 static void checkTagType(const Symbol *existing, const InputFile *file, 172 const WasmSignature *newSig) { 173 const auto *existingTag = dyn_cast<TagSymbol>(existing); 174 if (!isa<TagSymbol>(existing)) { 175 reportTypeError(existing, file, WASM_SYMBOL_TYPE_TAG); 176 return; 177 } 178 179 const WasmSignature *oldSig = existingTag->signature; 180 if (*newSig != *oldSig) 181 warn("Tag signature mismatch: " + existing->getName() + 182 "\n>>> defined as " + toString(*oldSig) + " in " + 183 toString(existing->getFile()) + "\n>>> defined as " + 184 toString(*newSig) + " in " + toString(file)); 185 } 186 187 static void checkTableType(const Symbol *existing, const InputFile *file, 188 const WasmTableType *newType) { 189 if (!isa<TableSymbol>(existing)) { 190 reportTypeError(existing, file, WASM_SYMBOL_TYPE_TABLE); 191 return; 192 } 193 194 const WasmTableType *oldType = cast<TableSymbol>(existing)->getTableType(); 195 if (newType->ElemType != oldType->ElemType) { 196 error("Table type mismatch: " + existing->getName() + "\n>>> defined as " + 197 toString(*oldType) + " in " + toString(existing->getFile()) + 198 "\n>>> defined as " + toString(*newType) + " in " + toString(file)); 199 } 200 // FIXME: No assertions currently on the limits. 201 } 202 203 static void checkDataType(const Symbol *existing, const InputFile *file) { 204 if (!isa<DataSymbol>(existing)) 205 reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA); 206 } 207 208 DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name, 209 uint32_t flags, 210 InputFunction *function) { 211 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << name << "\n"); 212 assert(!find(name)); 213 syntheticFunctions.emplace_back(function); 214 return replaceSymbol<DefinedFunction>(insertName(name).first, name, 215 flags, nullptr, function); 216 } 217 218 // Adds an optional, linker generated, data symbol. The symbol will only be 219 // added if there is an undefine reference to it, or if it is explicitly 220 // exported via the --export flag. Otherwise we don't add the symbol and return 221 // nullptr. 222 DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name, 223 uint64_t value) { 224 Symbol *s = find(name); 225 if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0)) 226 s = insertName(name).first; 227 else if (!s || s->isDefined()) 228 return nullptr; 229 LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n"); 230 auto *rtn = replaceSymbol<DefinedData>(s, name, WASM_SYMBOL_VISIBILITY_HIDDEN); 231 rtn->setVA(value); 232 rtn->referenced = true; 233 return rtn; 234 } 235 236 DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name, 237 uint32_t flags) { 238 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n"); 239 assert(!find(name)); 240 return replaceSymbol<DefinedData>(insertName(name).first, name, flags); 241 } 242 243 DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags, 244 InputGlobal *global) { 245 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << name << " -> " << global 246 << "\n"); 247 assert(!find(name)); 248 syntheticGlobals.emplace_back(global); 249 return replaceSymbol<DefinedGlobal>(insertName(name).first, name, flags, 250 nullptr, global); 251 } 252 253 DefinedGlobal *SymbolTable::addOptionalGlobalSymbol(StringRef name, 254 InputGlobal *global) { 255 Symbol *s = find(name); 256 if (!s || s->isDefined()) 257 return nullptr; 258 LLVM_DEBUG(dbgs() << "addOptionalGlobalSymbol: " << name << " -> " << global 259 << "\n"); 260 syntheticGlobals.emplace_back(global); 261 return replaceSymbol<DefinedGlobal>(s, name, WASM_SYMBOL_VISIBILITY_HIDDEN, 262 nullptr, global); 263 } 264 265 DefinedTable *SymbolTable::addSyntheticTable(StringRef name, uint32_t flags, 266 InputTable *table) { 267 LLVM_DEBUG(dbgs() << "addSyntheticTable: " << name << " -> " << table 268 << "\n"); 269 Symbol *s = find(name); 270 assert(!s || s->isUndefined()); 271 if (!s) 272 s = insertName(name).first; 273 syntheticTables.emplace_back(table); 274 return replaceSymbol<DefinedTable>(s, name, flags, nullptr, table); 275 } 276 277 static bool shouldReplace(const Symbol *existing, InputFile *newFile, 278 uint32_t newFlags) { 279 // If existing symbol is undefined, replace it. 280 if (!existing->isDefined()) { 281 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 282 << existing->getName() << "\n"); 283 return true; 284 } 285 286 // Now we have two defined symbols. If the new one is weak, we can ignore it. 287 if ((newFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 288 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 289 return false; 290 } 291 292 // If the existing symbol is weak, we should replace it. 293 if (existing->isWeak()) { 294 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 295 return true; 296 } 297 298 // Neither symbol is week. They conflict. 299 error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " + 300 toString(existing->getFile()) + "\n>>> defined in " + 301 toString(newFile)); 302 return true; 303 } 304 305 Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags, 306 InputFile *file, 307 InputFunction *function) { 308 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << name << " [" 309 << (function ? toString(function->signature) : "none") 310 << "]\n"); 311 Symbol *s; 312 bool wasInserted; 313 std::tie(s, wasInserted) = insert(name, file); 314 315 auto replaceSym = [&](Symbol *sym) { 316 // If the new defined function doesn't have signature (i.e. bitcode 317 // functions) but the old symbol does, then preserve the old signature 318 const WasmSignature *oldSig = s->getSignature(); 319 auto* newSym = replaceSymbol<DefinedFunction>(sym, name, flags, file, function); 320 if (!newSym->signature) 321 newSym->signature = oldSig; 322 }; 323 324 if (wasInserted || s->isLazy()) { 325 replaceSym(s); 326 return s; 327 } 328 329 auto existingFunction = dyn_cast<FunctionSymbol>(s); 330 if (!existingFunction) { 331 reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); 332 return s; 333 } 334 335 bool checkSig = true; 336 if (auto ud = dyn_cast<UndefinedFunction>(existingFunction)) 337 checkSig = ud->isCalledDirectly; 338 339 if (checkSig && function && !signatureMatches(existingFunction, &function->signature)) { 340 Symbol* variant; 341 if (getFunctionVariant(s, &function->signature, file, &variant)) 342 // New variant, always replace 343 replaceSym(variant); 344 else if (shouldReplace(s, file, flags)) 345 // Variant already exists, replace it after checking shouldReplace 346 replaceSym(variant); 347 348 // This variant we found take the place in the symbol table as the primary 349 // variant. 350 replace(name, variant); 351 return variant; 352 } 353 354 // Existing function with matching signature. 355 if (shouldReplace(s, file, flags)) 356 replaceSym(s); 357 358 return s; 359 } 360 361 Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags, 362 InputFile *file, InputChunk *segment, 363 uint64_t address, uint64_t size) { 364 LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address 365 << "\n"); 366 Symbol *s; 367 bool wasInserted; 368 std::tie(s, wasInserted) = insert(name, file); 369 370 auto replaceSym = [&]() { 371 replaceSymbol<DefinedData>(s, name, flags, file, segment, address, size); 372 }; 373 374 if (wasInserted || s->isLazy()) { 375 replaceSym(); 376 return s; 377 } 378 379 checkDataType(s, file); 380 381 if (shouldReplace(s, file, flags)) 382 replaceSym(); 383 return s; 384 } 385 386 Symbol *SymbolTable::addDefinedGlobal(StringRef name, uint32_t flags, 387 InputFile *file, InputGlobal *global) { 388 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << name << "\n"); 389 390 Symbol *s; 391 bool wasInserted; 392 std::tie(s, wasInserted) = insert(name, file); 393 394 auto replaceSym = [&]() { 395 replaceSymbol<DefinedGlobal>(s, name, flags, file, global); 396 }; 397 398 if (wasInserted || s->isLazy()) { 399 replaceSym(); 400 return s; 401 } 402 403 checkGlobalType(s, file, &global->getType()); 404 405 if (shouldReplace(s, file, flags)) 406 replaceSym(); 407 return s; 408 } 409 410 Symbol *SymbolTable::addDefinedTag(StringRef name, uint32_t flags, 411 InputFile *file, InputTag *tag) { 412 LLVM_DEBUG(dbgs() << "addDefinedTag:" << name << "\n"); 413 414 Symbol *s; 415 bool wasInserted; 416 std::tie(s, wasInserted) = insert(name, file); 417 418 auto replaceSym = [&]() { 419 replaceSymbol<DefinedTag>(s, name, flags, file, tag); 420 }; 421 422 if (wasInserted || s->isLazy()) { 423 replaceSym(); 424 return s; 425 } 426 427 checkTagType(s, file, &tag->signature); 428 429 if (shouldReplace(s, file, flags)) 430 replaceSym(); 431 return s; 432 } 433 434 Symbol *SymbolTable::addDefinedTable(StringRef name, uint32_t flags, 435 InputFile *file, InputTable *table) { 436 LLVM_DEBUG(dbgs() << "addDefinedTable:" << name << "\n"); 437 438 Symbol *s; 439 bool wasInserted; 440 std::tie(s, wasInserted) = insert(name, file); 441 442 auto replaceSym = [&]() { 443 replaceSymbol<DefinedTable>(s, name, flags, file, table); 444 }; 445 446 if (wasInserted || s->isLazy()) { 447 replaceSym(); 448 return s; 449 } 450 451 checkTableType(s, file, &table->getType()); 452 453 if (shouldReplace(s, file, flags)) 454 replaceSym(); 455 return s; 456 } 457 458 // This function get called when an undefined symbol is added, and there is 459 // already an existing one in the symbols table. In this case we check that 460 // custom 'import-module' and 'import-field' symbol attributes agree. 461 // With LTO these attributes are not available when the bitcode is read and only 462 // become available when the LTO object is read. In this case we silently 463 // replace the empty attributes with the valid ones. 464 template <typename T> 465 static void setImportAttributes(T *existing, Optional<StringRef> importName, 466 Optional<StringRef> importModule, 467 uint32_t flags, InputFile *file) { 468 if (importName) { 469 if (!existing->importName) 470 existing->importName = importName; 471 if (existing->importName != importName) 472 error("import name mismatch for symbol: " + toString(*existing) + 473 "\n>>> defined as " + *existing->importName + " in " + 474 toString(existing->getFile()) + "\n>>> defined as " + *importName + 475 " in " + toString(file)); 476 } 477 478 if (importModule) { 479 if (!existing->importModule) 480 existing->importModule = importModule; 481 if (existing->importModule != importModule) 482 error("import module mismatch for symbol: " + toString(*existing) + 483 "\n>>> defined as " + *existing->importModule + " in " + 484 toString(existing->getFile()) + "\n>>> defined as " + 485 *importModule + " in " + toString(file)); 486 } 487 488 // Update symbol binding, if the existing symbol is weak 489 uint32_t binding = flags & WASM_SYMBOL_BINDING_MASK; 490 if (existing->isWeak() && binding != WASM_SYMBOL_BINDING_WEAK) { 491 existing->flags = (existing->flags & ~WASM_SYMBOL_BINDING_MASK) | binding; 492 } 493 } 494 495 Symbol *SymbolTable::addUndefinedFunction(StringRef name, 496 Optional<StringRef> importName, 497 Optional<StringRef> importModule, 498 uint32_t flags, InputFile *file, 499 const WasmSignature *sig, 500 bool isCalledDirectly) { 501 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << name << " [" 502 << (sig ? toString(*sig) : "none") 503 << "] IsCalledDirectly:" << isCalledDirectly << " flags=0x" 504 << utohexstr(flags) << "\n"); 505 assert(flags & WASM_SYMBOL_UNDEFINED); 506 507 Symbol *s; 508 bool wasInserted; 509 std::tie(s, wasInserted) = insert(name, file); 510 if (s->traced) 511 printTraceSymbolUndefined(name, file); 512 513 auto replaceSym = [&]() { 514 replaceSymbol<UndefinedFunction>(s, name, importName, importModule, flags, 515 file, sig, isCalledDirectly); 516 }; 517 518 if (wasInserted) { 519 replaceSym(); 520 } else if (auto *lazy = dyn_cast<LazySymbol>(s)) { 521 if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 522 lazy->setWeak(); 523 lazy->signature = sig; 524 } else { 525 lazy->fetch(); 526 } 527 } else { 528 auto existingFunction = dyn_cast<FunctionSymbol>(s); 529 if (!existingFunction) { 530 reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); 531 return s; 532 } 533 if (!existingFunction->signature && sig) 534 existingFunction->signature = sig; 535 auto *existingUndefined = dyn_cast<UndefinedFunction>(existingFunction); 536 if (isCalledDirectly && !signatureMatches(existingFunction, sig)) { 537 // If the existing undefined functions is not called directly then let 538 // this one take precedence. Otherwise the existing function is either 539 // directly called or defined, in which case we need a function variant. 540 if (existingUndefined && !existingUndefined->isCalledDirectly) 541 replaceSym(); 542 else if (getFunctionVariant(s, sig, file, &s)) 543 replaceSym(); 544 } 545 if (existingUndefined) { 546 setImportAttributes(existingUndefined, importName, importModule, flags, 547 file); 548 if (isCalledDirectly) 549 existingUndefined->isCalledDirectly = true; 550 } 551 } 552 553 return s; 554 } 555 556 Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags, 557 InputFile *file) { 558 LLVM_DEBUG(dbgs() << "addUndefinedData: " << name << "\n"); 559 assert(flags & WASM_SYMBOL_UNDEFINED); 560 561 Symbol *s; 562 bool wasInserted; 563 std::tie(s, wasInserted) = insert(name, file); 564 if (s->traced) 565 printTraceSymbolUndefined(name, file); 566 567 if (wasInserted) { 568 replaceSymbol<UndefinedData>(s, name, flags, file); 569 } else if (auto *lazy = dyn_cast<LazySymbol>(s)) { 570 if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) 571 lazy->setWeak(); 572 else 573 lazy->fetch(); 574 } else if (s->isDefined()) { 575 checkDataType(s, file); 576 } 577 return s; 578 } 579 580 Symbol *SymbolTable::addUndefinedGlobal(StringRef name, 581 Optional<StringRef> importName, 582 Optional<StringRef> importModule, 583 uint32_t flags, InputFile *file, 584 const WasmGlobalType *type) { 585 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n"); 586 assert(flags & WASM_SYMBOL_UNDEFINED); 587 588 Symbol *s; 589 bool wasInserted; 590 std::tie(s, wasInserted) = insert(name, file); 591 if (s->traced) 592 printTraceSymbolUndefined(name, file); 593 594 if (wasInserted) 595 replaceSymbol<UndefinedGlobal>(s, name, importName, importModule, flags, 596 file, type); 597 else if (auto *lazy = dyn_cast<LazySymbol>(s)) 598 lazy->fetch(); 599 else if (s->isDefined()) 600 checkGlobalType(s, file, type); 601 return s; 602 } 603 604 Symbol *SymbolTable::addUndefinedTable(StringRef name, 605 Optional<StringRef> importName, 606 Optional<StringRef> importModule, 607 uint32_t flags, InputFile *file, 608 const WasmTableType *type) { 609 LLVM_DEBUG(dbgs() << "addUndefinedTable: " << name << "\n"); 610 assert(flags & WASM_SYMBOL_UNDEFINED); 611 612 Symbol *s; 613 bool wasInserted; 614 std::tie(s, wasInserted) = insert(name, file); 615 if (s->traced) 616 printTraceSymbolUndefined(name, file); 617 618 if (wasInserted) 619 replaceSymbol<UndefinedTable>(s, name, importName, importModule, flags, 620 file, type); 621 else if (auto *lazy = dyn_cast<LazySymbol>(s)) 622 lazy->fetch(); 623 else if (s->isDefined()) 624 checkTableType(s, file, type); 625 return s; 626 } 627 628 TableSymbol *SymbolTable::createUndefinedIndirectFunctionTable(StringRef name) { 629 WasmLimits limits{0, 0, 0}; // Set by the writer. 630 WasmTableType *type = make<WasmTableType>(); 631 type->ElemType = uint8_t(ValType::FUNCREF); 632 type->Limits = limits; 633 StringRef module(defaultModule); 634 uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN; 635 flags |= WASM_SYMBOL_UNDEFINED; 636 Symbol *sym = addUndefinedTable(name, name, module, flags, nullptr, type); 637 sym->markLive(); 638 sym->forceExport = config->exportTable; 639 return cast<TableSymbol>(sym); 640 } 641 642 TableSymbol *SymbolTable::createDefinedIndirectFunctionTable(StringRef name) { 643 const uint32_t invalidIndex = -1; 644 WasmLimits limits{0, 0, 0}; // Set by the writer. 645 WasmTableType type{uint8_t(ValType::FUNCREF), limits}; 646 WasmTable desc{invalidIndex, type, name}; 647 InputTable *table = make<InputTable>(desc, nullptr); 648 uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN; 649 TableSymbol *sym = addSyntheticTable(name, flags, table); 650 sym->markLive(); 651 sym->forceExport = config->exportTable; 652 return sym; 653 } 654 655 // Whether or not we need an indirect function table is usually a function of 656 // whether an input declares a need for it. However sometimes it's possible for 657 // no input to need the indirect function table, but then a late 658 // addInternalGOTEntry causes a function to be allocated an address. In that 659 // case address we synthesize a definition at the last minute. 660 TableSymbol *SymbolTable::resolveIndirectFunctionTable(bool required) { 661 Symbol *existing = find(functionTableName); 662 if (existing) { 663 if (!isa<TableSymbol>(existing)) { 664 error(Twine("reserved symbol must be of type table: `") + 665 functionTableName + "`"); 666 return nullptr; 667 } 668 if (existing->isDefined()) { 669 error(Twine("reserved symbol must not be defined in input files: `") + 670 functionTableName + "`"); 671 return nullptr; 672 } 673 } 674 675 if (config->importTable) { 676 if (existing) 677 return cast<TableSymbol>(existing); 678 if (required) 679 return createUndefinedIndirectFunctionTable(functionTableName); 680 } else if ((existing && existing->isLive()) || config->exportTable || 681 required) { 682 // A defined table is required. Either because the user request an exported 683 // table or because the table symbol is already live. The existing table is 684 // guaranteed to be undefined due to the check above. 685 return createDefinedIndirectFunctionTable(functionTableName); 686 } 687 688 // An indirect function table will only be present in the symbol table if 689 // needed by a reloc; if we get here, we don't need one. 690 return nullptr; 691 } 692 693 void SymbolTable::addLazy(ArchiveFile *file, const Archive::Symbol *sym) { 694 LLVM_DEBUG(dbgs() << "addLazy: " << sym->getName() << "\n"); 695 StringRef name = sym->getName(); 696 697 Symbol *s; 698 bool wasInserted; 699 std::tie(s, wasInserted) = insertName(name); 700 701 if (wasInserted) { 702 replaceSymbol<LazySymbol>(s, name, 0, file, *sym); 703 return; 704 } 705 706 if (!s->isUndefined()) 707 return; 708 709 // The existing symbol is undefined, load a new one from the archive, 710 // unless the existing symbol is weak in which case replace the undefined 711 // symbols with a LazySymbol. 712 if (s->isWeak()) { 713 const WasmSignature *oldSig = nullptr; 714 // In the case of an UndefinedFunction we need to preserve the expected 715 // signature. 716 if (auto *f = dyn_cast<UndefinedFunction>(s)) 717 oldSig = f->signature; 718 LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); 719 auto newSym = replaceSymbol<LazySymbol>(s, name, WASM_SYMBOL_BINDING_WEAK, 720 file, *sym); 721 newSym->signature = oldSig; 722 return; 723 } 724 725 LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 726 file->addMember(sym); 727 } 728 729 bool SymbolTable::addComdat(StringRef name) { 730 return comdatGroups.insert(CachedHashStringRef(name)).second; 731 } 732 733 // The new signature doesn't match. Create a variant to the symbol with the 734 // signature encoded in the name and return that instead. These symbols are 735 // then unified later in handleSymbolVariants. 736 bool SymbolTable::getFunctionVariant(Symbol* sym, const WasmSignature *sig, 737 const InputFile *file, Symbol **out) { 738 LLVM_DEBUG(dbgs() << "getFunctionVariant: " << sym->getName() << " -> " 739 << " " << toString(*sig) << "\n"); 740 Symbol *variant = nullptr; 741 742 // Linear search through symbol variants. Should never be more than two 743 // or three entries here. 744 auto &variants = symVariants[CachedHashStringRef(sym->getName())]; 745 if (variants.empty()) 746 variants.push_back(sym); 747 748 for (Symbol* v : variants) { 749 if (*v->getSignature() == *sig) { 750 variant = v; 751 break; 752 } 753 } 754 755 bool wasAdded = !variant; 756 if (wasAdded) { 757 // Create a new variant; 758 LLVM_DEBUG(dbgs() << "added new variant\n"); 759 variant = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 760 variant->isUsedInRegularObj = 761 !file || file->kind() == InputFile::ObjectKind; 762 variant->canInline = true; 763 variant->traced = false; 764 variant->forceExport = false; 765 variants.push_back(variant); 766 } else { 767 LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*variant) << "\n"); 768 assert(*variant->getSignature() == *sig); 769 } 770 771 *out = variant; 772 return wasAdded; 773 } 774 775 // Set a flag for --trace-symbol so that we can print out a log message 776 // if a new symbol with the same name is inserted into the symbol table. 777 void SymbolTable::trace(StringRef name) { 778 symMap.insert({CachedHashStringRef(name), -1}); 779 } 780 781 void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { 782 // Swap symbols as instructed by -wrap. 783 int &origIdx = symMap[CachedHashStringRef(sym->getName())]; 784 int &realIdx= symMap[CachedHashStringRef(real->getName())]; 785 int &wrapIdx = symMap[CachedHashStringRef(wrap->getName())]; 786 LLVM_DEBUG(dbgs() << "wrap: " << sym->getName() << "\n"); 787 788 // Anyone looking up __real symbols should get the original 789 realIdx = origIdx; 790 // Anyone looking up the original should get the __wrap symbol 791 origIdx = wrapIdx; 792 } 793 794 static const uint8_t unreachableFn[] = { 795 0x03 /* ULEB length */, 0x00 /* ULEB num locals */, 796 0x00 /* opcode unreachable */, 0x0b /* opcode end */ 797 }; 798 799 // Replace the given symbol body with an unreachable function. 800 // This is used by handleWeakUndefines in order to generate a callable 801 // equivalent of an undefined function and also handleSymbolVariants for 802 // undefined functions that don't match the signature of the definition. 803 InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym, 804 const WasmSignature &sig, 805 StringRef debugName) { 806 auto *func = make<SyntheticFunction>(sig, sym->getName(), debugName); 807 func->setBody(unreachableFn); 808 syntheticFunctions.emplace_back(func); 809 // Mark new symbols as local. For relocatable output we don't want them 810 // to be exported outside the object file. 811 replaceSymbol<DefinedFunction>(sym, debugName, WASM_SYMBOL_BINDING_LOCAL, 812 nullptr, func); 813 // Ensure the stub function doesn't get a table entry. Its address 814 // should always compare equal to the null pointer. 815 sym->isStub = true; 816 return func; 817 } 818 819 void SymbolTable::replaceWithUndefined(Symbol *sym) { 820 // Add a synthetic dummy for weak undefined functions. These dummies will 821 // be GC'd if not used as the target of any "call" instructions. 822 StringRef debugName = saver.save("undefined_weak:" + toString(*sym)); 823 replaceWithUnreachable(sym, *sym->getSignature(), debugName); 824 // Hide our dummy to prevent export. 825 sym->setHidden(true); 826 } 827 828 // For weak undefined functions, there may be "call" instructions that reference 829 // the symbol. In this case, we need to synthesise a dummy/stub function that 830 // will abort at runtime, so that relocations can still provided an operand to 831 // the call instruction that passes Wasm validation. 832 void SymbolTable::handleWeakUndefines() { 833 for (Symbol *sym : getSymbols()) { 834 if (sym->isUndefWeak()) { 835 if (sym->getSignature()) { 836 replaceWithUndefined(sym); 837 } else { 838 // It is possible for undefined functions not to have a signature (eg. 839 // if added via "--undefined"), but weak undefined ones do have a 840 // signature. Lazy symbols may not be functions and therefore Sig can 841 // still be null in some circumstance. 842 assert(!isa<FunctionSymbol>(sym)); 843 } 844 } 845 } 846 } 847 848 DefinedFunction *SymbolTable::createUndefinedStub(const WasmSignature &sig) { 849 if (stubFunctions.count(sig)) 850 return stubFunctions[sig]; 851 LLVM_DEBUG(dbgs() << "createUndefinedStub: " << toString(sig) << "\n"); 852 auto *sym = reinterpret_cast<DefinedFunction *>(make<SymbolUnion>()); 853 sym->isUsedInRegularObj = true; 854 sym->canInline = true; 855 sym->traced = false; 856 sym->forceExport = false; 857 sym->signature = &sig; 858 replaceSymbol<DefinedFunction>( 859 sym, "undefined_stub", WASM_SYMBOL_VISIBILITY_HIDDEN, nullptr, nullptr); 860 replaceWithUnreachable(sym, sig, "undefined_stub"); 861 stubFunctions[sig] = sym; 862 return sym; 863 } 864 865 static void reportFunctionSignatureMismatch(StringRef symName, 866 FunctionSymbol *a, 867 FunctionSymbol *b, bool isError) { 868 std::string msg = ("function signature mismatch: " + symName + 869 "\n>>> defined as " + toString(*a->signature) + " in " + 870 toString(a->getFile()) + "\n>>> defined as " + 871 toString(*b->signature) + " in " + toString(b->getFile())) 872 .str(); 873 if (isError) 874 error(msg); 875 else 876 warn(msg); 877 } 878 879 // Remove any variant symbols that were created due to function signature 880 // mismatches. 881 void SymbolTable::handleSymbolVariants() { 882 for (auto pair : symVariants) { 883 // Push the initial symbol onto the list of variants. 884 StringRef symName = pair.first.val(); 885 std::vector<Symbol *> &variants = pair.second; 886 887 #ifndef NDEBUG 888 LLVM_DEBUG(dbgs() << "symbol with (" << variants.size() 889 << ") variants: " << symName << "\n"); 890 for (auto *s: variants) { 891 auto *f = cast<FunctionSymbol>(s); 892 LLVM_DEBUG(dbgs() << " variant: " + f->getName() << " " 893 << toString(*f->signature) << "\n"); 894 } 895 #endif 896 897 // Find the one definition. 898 DefinedFunction *defined = nullptr; 899 for (auto *symbol : variants) { 900 if (auto f = dyn_cast<DefinedFunction>(symbol)) { 901 defined = f; 902 break; 903 } 904 } 905 906 // If there are no definitions, and the undefined symbols disagree on 907 // the signature, there is not we can do since we don't know which one 908 // to use as the signature on the import. 909 if (!defined) { 910 reportFunctionSignatureMismatch(symName, 911 cast<FunctionSymbol>(variants[0]), 912 cast<FunctionSymbol>(variants[1]), true); 913 return; 914 } 915 916 for (auto *symbol : variants) { 917 if (symbol != defined) { 918 auto *f = cast<FunctionSymbol>(symbol); 919 reportFunctionSignatureMismatch(symName, f, defined, false); 920 StringRef debugName = saver.save("signature_mismatch:" + toString(*f)); 921 replaceWithUnreachable(f, *f->signature, debugName); 922 } 923 } 924 } 925 } 926 927 } // namespace wasm 928 } // namespace lld 929