1c94d393aSSam Clegg //===- SymbolTable.cpp ----------------------------------------------------===// 2c94d393aSSam Clegg // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c94d393aSSam Clegg // 7c94d393aSSam Clegg //===----------------------------------------------------------------------===// 8c94d393aSSam Clegg 9c94d393aSSam Clegg #include "SymbolTable.h" 10c94d393aSSam Clegg #include "Config.h" 115fa274beSSam Clegg #include "InputChunks.h" 12e915a71fSHeejin Ahn #include "InputEvent.h" 1393102974SSam Clegg #include "InputGlobal.h" 14b8621596SSam Clegg #include "WriterUtils.h" 15c94d393aSSam Clegg #include "lld/Common/ErrorHandler.h" 162017d52bSRui Ueyama #include "lld/Common/Memory.h" 177d67dd11SRui Ueyama #include "llvm/ADT/SetVector.h" 18c94d393aSSam Clegg 19c94d393aSSam Clegg #define DEBUG_TYPE "lld" 20c94d393aSSam Clegg 21c94d393aSSam Clegg using namespace llvm; 2220db381bSSam Clegg using namespace llvm::wasm; 2345218f4aSSam Clegg using namespace llvm::object; 24c94d393aSSam Clegg using namespace lld; 25c94d393aSSam Clegg using namespace lld::wasm; 26c94d393aSSam Clegg 27*136d27abSRui Ueyama SymbolTable *lld::wasm::symtab; 28c94d393aSSam Clegg 29*136d27abSRui Ueyama void SymbolTable::addFile(InputFile *file) { 30*136d27abSRui Ueyama log("Processing: " + toString(file)); 31a282a61bSSam Clegg 32a282a61bSSam Clegg // .a file 33*136d27abSRui Ueyama if (auto *f = dyn_cast<ArchiveFile>(file)) { 34*136d27abSRui Ueyama f->parse(); 35a282a61bSSam Clegg return; 36a282a61bSSam Clegg } 37a282a61bSSam Clegg 38a282a61bSSam Clegg // .so file 39*136d27abSRui Ueyama if (auto *f = dyn_cast<SharedFile>(file)) { 40*136d27abSRui Ueyama sharedFiles.push_back(f); 41a282a61bSSam Clegg return; 42a282a61bSSam Clegg } 43a282a61bSSam Clegg 44*136d27abSRui Ueyama if (config->trace) 45*136d27abSRui Ueyama message(toString(file)); 46c94d393aSSam Clegg 47c729c1b4SSam Clegg // LLVM bitcode file 48*136d27abSRui Ueyama if (auto *f = dyn_cast<BitcodeFile>(file)) { 49*136d27abSRui Ueyama f->parse(); 50*136d27abSRui Ueyama bitcodeFiles.push_back(f); 51a282a61bSSam Clegg return; 52a282a61bSSam Clegg } 53a282a61bSSam Clegg 54a282a61bSSam Clegg // Regular object file 55*136d27abSRui Ueyama auto *f = cast<ObjFile>(file); 56*136d27abSRui Ueyama f->parse(false); 57*136d27abSRui Ueyama objectFiles.push_back(f); 58c94d393aSSam Clegg } 59c94d393aSSam Clegg 60c729c1b4SSam Clegg // This function is where all the optimizations of link-time 61c729c1b4SSam Clegg // optimization happens. When LTO is in use, some input files are 62c729c1b4SSam Clegg // not in native object file format but in the LLVM bitcode format. 63c729c1b4SSam Clegg // This function compiles bitcode files into a few big native files 64c729c1b4SSam Clegg // using LLVM functions and replaces bitcode symbols with the results. 65c729c1b4SSam Clegg // Because all bitcode files that the program consists of are passed 66c729c1b4SSam Clegg // to the compiler at once, it can do whole-program optimization. 67c729c1b4SSam Clegg void SymbolTable::addCombinedLTOObject() { 68*136d27abSRui Ueyama if (bitcodeFiles.empty()) 69c729c1b4SSam Clegg return; 70c729c1b4SSam Clegg 71c729c1b4SSam Clegg // Compile bitcode files and replace bitcode symbols. 72*136d27abSRui Ueyama lto.reset(new BitcodeCompiler); 73*136d27abSRui Ueyama for (BitcodeFile *f : bitcodeFiles) 74*136d27abSRui Ueyama lto->add(*f); 75c729c1b4SSam Clegg 76*136d27abSRui Ueyama for (StringRef filename : lto->compile()) { 77*136d27abSRui Ueyama auto *obj = make<ObjFile>(MemoryBufferRef(filename, "lto.tmp"), ""); 78*136d27abSRui Ueyama obj->parse(true); 79*136d27abSRui Ueyama objectFiles.push_back(obj); 80c729c1b4SSam Clegg } 81c729c1b4SSam Clegg } 82c729c1b4SSam Clegg 83*136d27abSRui Ueyama Symbol *SymbolTable::find(StringRef name) { 84*136d27abSRui Ueyama auto it = symMap.find(CachedHashStringRef(name)); 85*136d27abSRui Ueyama if (it == symMap.end() || it->second == -1) 861f3f774fSSam Clegg return nullptr; 87*136d27abSRui Ueyama return symVector[it->second]; 881f3f774fSSam Clegg } 891f3f774fSSam Clegg 90*136d27abSRui Ueyama void SymbolTable::replace(StringRef name, Symbol* sym) { 91*136d27abSRui Ueyama auto it = symMap.find(CachedHashStringRef(name)); 92*136d27abSRui Ueyama symVector[it->second] = sym; 936540e570SSam Clegg } 946540e570SSam Clegg 95*136d27abSRui Ueyama std::pair<Symbol *, bool> SymbolTable::insertName(StringRef name) { 96*136d27abSRui Ueyama bool trace = false; 97*136d27abSRui Ueyama auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); 98*136d27abSRui Ueyama int &symIndex = p.first->second; 99*136d27abSRui Ueyama bool isNew = p.second; 100*136d27abSRui Ueyama if (symIndex == -1) { 101*136d27abSRui Ueyama symIndex = symVector.size(); 102*136d27abSRui Ueyama trace = true; 103*136d27abSRui Ueyama isNew = true; 1041f3f774fSSam Clegg } 1051f3f774fSSam Clegg 106*136d27abSRui Ueyama if (!isNew) 107*136d27abSRui Ueyama return {symVector[symIndex], false}; 1081f3f774fSSam Clegg 109*136d27abSRui Ueyama Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 110*136d27abSRui Ueyama sym->isUsedInRegularObj = false; 111*136d27abSRui Ueyama sym->canInline = true; 112*136d27abSRui Ueyama sym->traced = trace; 113*136d27abSRui Ueyama symVector.emplace_back(sym); 114*136d27abSRui Ueyama return {sym, true}; 115c94d393aSSam Clegg } 116c94d393aSSam Clegg 117*136d27abSRui Ueyama std::pair<Symbol *, bool> SymbolTable::insert(StringRef name, 118*136d27abSRui Ueyama const InputFile *file) { 119*136d27abSRui Ueyama Symbol *s; 120*136d27abSRui Ueyama bool wasInserted; 121*136d27abSRui Ueyama std::tie(s, wasInserted) = insertName(name); 1221f3f774fSSam Clegg 123*136d27abSRui Ueyama if (!file || file->kind() == InputFile::ObjectKind) 124*136d27abSRui Ueyama s->isUsedInRegularObj = true; 1251f3f774fSSam Clegg 126*136d27abSRui Ueyama return {s, wasInserted}; 127c94d393aSSam Clegg } 128c94d393aSSam Clegg 129*136d27abSRui Ueyama static void reportTypeError(const Symbol *existing, const InputFile *file, 130*136d27abSRui Ueyama llvm::wasm::WasmSymbolType type) { 131*136d27abSRui Ueyama error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " + 132*136d27abSRui Ueyama toString(existing->getWasmType()) + " in " + 133*136d27abSRui Ueyama toString(existing->getFile()) + "\n>>> defined as " + toString(type) + 134*136d27abSRui Ueyama " in " + toString(file)); 135e3498ec5SRui Ueyama } 136e3498ec5SRui Ueyama 1376f4286fbSHeejin Ahn // Check the type of new symbol matches that of the symbol is replacing. 1386540e570SSam Clegg // Returns true if the function types match, false is there is a singature 1396540e570SSam Clegg // mismatch. 140*136d27abSRui Ueyama static bool signatureMatches(FunctionSymbol *existing, 141*136d27abSRui Ueyama const WasmSignature *newSig) { 142*136d27abSRui Ueyama const WasmSignature *oldSig = existing->signature; 143d506b0a4SSam Clegg 144d506b0a4SSam Clegg // If either function is missing a signature (this happend for bitcode 145d506b0a4SSam Clegg // symbols) then assume they match. Any mismatch will be reported later 146d506b0a4SSam Clegg // when the LTO objects are added. 147*136d27abSRui Ueyama if (!newSig || !oldSig) 1486540e570SSam Clegg return true; 149cefbf9acSSam Clegg 150*136d27abSRui Ueyama return *newSig == *oldSig; 151e3498ec5SRui Ueyama } 152e3498ec5SRui Ueyama 153*136d27abSRui Ueyama static void checkGlobalType(const Symbol *existing, const InputFile *file, 154*136d27abSRui Ueyama const WasmGlobalType *newType) { 155*136d27abSRui Ueyama if (!isa<GlobalSymbol>(existing)) { 156*136d27abSRui Ueyama reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL); 157b8621596SSam Clegg return; 158b8621596SSam Clegg } 159b8621596SSam Clegg 160*136d27abSRui Ueyama const WasmGlobalType *oldType = cast<GlobalSymbol>(existing)->getGlobalType(); 161*136d27abSRui Ueyama if (*newType != *oldType) { 162*136d27abSRui Ueyama error("Global type mismatch: " + existing->getName() + "\n>>> defined as " + 163*136d27abSRui Ueyama toString(*oldType) + " in " + toString(existing->getFile()) + 164*136d27abSRui Ueyama "\n>>> defined as " + toString(*newType) + " in " + toString(file)); 165c94d393aSSam Clegg } 16624b3dcd4SSam Clegg } 16724b3dcd4SSam Clegg 168*136d27abSRui Ueyama static void checkEventType(const Symbol *existing, const InputFile *file, 169*136d27abSRui Ueyama const WasmEventType *newType, 170*136d27abSRui Ueyama const WasmSignature *newSig) { 171*136d27abSRui Ueyama auto existingEvent = dyn_cast<EventSymbol>(existing); 172*136d27abSRui Ueyama if (!isa<EventSymbol>(existing)) { 173*136d27abSRui Ueyama reportTypeError(existing, file, WASM_SYMBOL_TYPE_EVENT); 174e915a71fSHeejin Ahn return; 175e915a71fSHeejin Ahn } 176e915a71fSHeejin Ahn 177*136d27abSRui Ueyama const WasmEventType *oldType = cast<EventSymbol>(existing)->getEventType(); 178*136d27abSRui Ueyama const WasmSignature *oldSig = existingEvent->signature; 179*136d27abSRui Ueyama if (newType->Attribute != oldType->Attribute) 180*136d27abSRui Ueyama error("Event type mismatch: " + existing->getName() + "\n>>> defined as " + 181*136d27abSRui Ueyama toString(*oldType) + " in " + toString(existing->getFile()) + 182*136d27abSRui Ueyama "\n>>> defined as " + toString(*newType) + " in " + toString(file)); 183*136d27abSRui Ueyama if (*newSig != *oldSig) 184*136d27abSRui Ueyama warn("Event signature mismatch: " + existing->getName() + 185*136d27abSRui Ueyama "\n>>> defined as " + toString(*oldSig) + " in " + 186*136d27abSRui Ueyama toString(existing->getFile()) + "\n>>> defined as " + 187*136d27abSRui Ueyama toString(*newSig) + " in " + toString(file)); 188e915a71fSHeejin Ahn } 189e915a71fSHeejin Ahn 190*136d27abSRui Ueyama static void checkDataType(const Symbol *existing, const InputFile *file) { 191*136d27abSRui Ueyama if (!isa<DataSymbol>(existing)) 192*136d27abSRui Ueyama reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA); 193e3498ec5SRui Ueyama } 194e3498ec5SRui Ueyama 195*136d27abSRui Ueyama DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name, 196*136d27abSRui Ueyama uint32_t flags, 197*136d27abSRui Ueyama InputFunction *function) { 198*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << name << "\n"); 199*136d27abSRui Ueyama assert(!find(name)); 200*136d27abSRui Ueyama syntheticFunctions.emplace_back(function); 201*136d27abSRui Ueyama return replaceSymbol<DefinedFunction>(insertName(name).first, name, 202*136d27abSRui Ueyama flags, nullptr, function); 20350686856SSam Clegg } 20450686856SSam Clegg 2058e8ddaa3SSam Clegg // Adds an optional, linker generated, data symbols. The symbol will only be 2068e8ddaa3SSam Clegg // added if there is an undefine reference to it, or if it is explictly exported 2078e8ddaa3SSam Clegg // via the --export flag. Otherwise we don't add the symbol and return nullptr. 208*136d27abSRui Ueyama DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name, uint32_t value, 209*136d27abSRui Ueyama uint32_t flags) { 210*136d27abSRui Ueyama Symbol *s = find(name); 211*136d27abSRui Ueyama if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0)) 212*136d27abSRui Ueyama s = insertName(name).first; 213*136d27abSRui Ueyama else if (!s || s->isDefined()) 2144bce63a0SSam Clegg return nullptr; 215*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n"); 216*136d27abSRui Ueyama auto *rtn = replaceSymbol<DefinedData>(s, name, flags); 217*136d27abSRui Ueyama rtn->setVirtualAddress(value); 218*136d27abSRui Ueyama rtn->referenced = true; 2194bce63a0SSam Clegg return rtn; 2204bce63a0SSam Clegg } 2214bce63a0SSam Clegg 222*136d27abSRui Ueyama DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name, 223*136d27abSRui Ueyama uint32_t flags) { 224*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n"); 225*136d27abSRui Ueyama assert(!find(name)); 226*136d27abSRui Ueyama return replaceSymbol<DefinedData>(insertName(name).first, name, flags); 227c94d393aSSam Clegg } 228c94d393aSSam Clegg 229*136d27abSRui Ueyama DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags, 230*136d27abSRui Ueyama InputGlobal *global) { 231*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << name << " -> " << global 232e7245b42SNicola Zaghen << "\n"); 233*136d27abSRui Ueyama assert(!find(name)); 234*136d27abSRui Ueyama syntheticGlobals.emplace_back(global); 235*136d27abSRui Ueyama return replaceSymbol<DefinedGlobal>(insertName(name).first, name, flags, 236*136d27abSRui Ueyama nullptr, global); 23793102974SSam Clegg } 23893102974SSam Clegg 239*136d27abSRui Ueyama static bool shouldReplace(const Symbol *existing, InputFile *newFile, 240*136d27abSRui Ueyama uint32_t newFlags) { 241c03c9040SRui Ueyama // If existing symbol is undefined, replace it. 242*136d27abSRui Ueyama if (!existing->isDefined()) { 243e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 244*136d27abSRui Ueyama << existing->getName() << "\n"); 245c03c9040SRui Ueyama return true; 246c03c9040SRui Ueyama } 247c03c9040SRui Ueyama 248c03c9040SRui Ueyama // Now we have two defined symbols. If the new one is weak, we can ignore it. 249*136d27abSRui Ueyama if ((newFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 250e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 251c03c9040SRui Ueyama return false; 252c03c9040SRui Ueyama } 253c03c9040SRui Ueyama 254c03c9040SRui Ueyama // If the existing symbol is weak, we should replace it. 255*136d27abSRui Ueyama if (existing->isWeak()) { 256e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 257c03c9040SRui Ueyama return true; 258c03c9040SRui Ueyama } 259c03c9040SRui Ueyama 260c03c9040SRui Ueyama // Neither symbol is week. They conflict. 261*136d27abSRui Ueyama error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " + 262*136d27abSRui Ueyama toString(existing->getFile()) + "\n>>> defined in " + 263*136d27abSRui Ueyama toString(newFile)); 264c03c9040SRui Ueyama return true; 265b8621596SSam Clegg } 26693e559b1SSam Clegg 267*136d27abSRui Ueyama Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags, 268*136d27abSRui Ueyama InputFile *file, 269*136d27abSRui Ueyama InputFunction *function) { 270*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addDefinedFunction: " << name << " [" 271*136d27abSRui Ueyama << (function ? toString(function->signature) : "none") 2728b0b48f3SSam Clegg << "]\n"); 273*136d27abSRui Ueyama Symbol *s; 274*136d27abSRui Ueyama bool wasInserted; 275*136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 276c729c1b4SSam Clegg 277*136d27abSRui Ueyama auto replaceSym = [&](Symbol *sym) { 2786540e570SSam Clegg // If the new defined function doesn't have signture (i.e. bitcode 2796540e570SSam Clegg // functions) but the old symbol does, then preserve the old signature 280*136d27abSRui Ueyama const WasmSignature *oldSig = s->getSignature(); 281*136d27abSRui Ueyama auto* newSym = replaceSymbol<DefinedFunction>(sym, name, flags, file, function); 282*136d27abSRui Ueyama if (!newSym->signature) 283*136d27abSRui Ueyama newSym->signature = oldSig; 2846540e570SSam Clegg }; 2856540e570SSam Clegg 286*136d27abSRui Ueyama if (wasInserted || s->isLazy()) { 287*136d27abSRui Ueyama replaceSym(s); 288*136d27abSRui Ueyama return s; 289e3498ec5SRui Ueyama } 290e3498ec5SRui Ueyama 291*136d27abSRui Ueyama auto existingFunction = dyn_cast<FunctionSymbol>(s); 292*136d27abSRui Ueyama if (!existingFunction) { 293*136d27abSRui Ueyama reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); 294*136d27abSRui Ueyama return s; 2958b0b48f3SSam Clegg } 2966540e570SSam Clegg 297*136d27abSRui Ueyama bool checkSig = true; 298*136d27abSRui Ueyama if (auto ud = dyn_cast<UndefinedFunction>(existingFunction)) 299*136d27abSRui Ueyama checkSig = ud->isCalledDirectly; 30059f959ffSSam Clegg 301*136d27abSRui Ueyama if (checkSig && function && !signatureMatches(existingFunction, &function->signature)) { 302*136d27abSRui Ueyama Symbol* variant; 303*136d27abSRui Ueyama if (getFunctionVariant(s, &function->signature, file, &variant)) 3046540e570SSam Clegg // New variant, always replace 305*136d27abSRui Ueyama replaceSym(variant); 306*136d27abSRui Ueyama else if (shouldReplace(s, file, flags)) 3076540e570SSam Clegg // Variant already exists, replace it after checking shouldReplace 308*136d27abSRui Ueyama replaceSym(variant); 3096540e570SSam Clegg 3106540e570SSam Clegg // This variant we found take the place in the symbol table as the primary 3116540e570SSam Clegg // variant. 312*136d27abSRui Ueyama replace(name, variant); 313*136d27abSRui Ueyama return variant; 3146540e570SSam Clegg } 3156540e570SSam Clegg 3166540e570SSam Clegg // Existing function with matching signature. 317*136d27abSRui Ueyama if (shouldReplace(s, file, flags)) 318*136d27abSRui Ueyama replaceSym(s); 3196540e570SSam Clegg 320*136d27abSRui Ueyama return s; 32193e559b1SSam Clegg } 32293e559b1SSam Clegg 323*136d27abSRui Ueyama Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags, 324*136d27abSRui Ueyama InputFile *file, InputSegment *segment, 325*136d27abSRui Ueyama uint32_t address, uint32_t size) { 326*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address 327e7245b42SNicola Zaghen << "\n"); 328*136d27abSRui Ueyama Symbol *s; 329*136d27abSRui Ueyama bool wasInserted; 330*136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 331c729c1b4SSam Clegg 332*136d27abSRui Ueyama auto replaceSym = [&]() { 333*136d27abSRui Ueyama replaceSymbol<DefinedData>(s, name, flags, file, segment, address, size); 3346540e570SSam Clegg }; 3356540e570SSam Clegg 336*136d27abSRui Ueyama if (wasInserted || s->isLazy()) { 337*136d27abSRui Ueyama replaceSym(); 338*136d27abSRui Ueyama return s; 339e3498ec5SRui Ueyama } 340e3498ec5SRui Ueyama 341*136d27abSRui Ueyama checkDataType(s, file); 342e3498ec5SRui Ueyama 343*136d27abSRui Ueyama if (shouldReplace(s, file, flags)) 344*136d27abSRui Ueyama replaceSym(); 345*136d27abSRui Ueyama return s; 346c94d393aSSam Clegg } 347c94d393aSSam Clegg 348*136d27abSRui Ueyama Symbol *SymbolTable::addDefinedGlobal(StringRef name, uint32_t flags, 349*136d27abSRui Ueyama InputFile *file, InputGlobal *global) { 350*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << name << "\n"); 3514c2cbfe6SSam Clegg 352*136d27abSRui Ueyama Symbol *s; 353*136d27abSRui Ueyama bool wasInserted; 354*136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 355c729c1b4SSam Clegg 356*136d27abSRui Ueyama auto replaceSym = [&]() { 357*136d27abSRui Ueyama replaceSymbol<DefinedGlobal>(s, name, flags, file, global); 3586540e570SSam Clegg }; 3596540e570SSam Clegg 360*136d27abSRui Ueyama if (wasInserted || s->isLazy()) { 361*136d27abSRui Ueyama replaceSym(); 362*136d27abSRui Ueyama return s; 36393102974SSam Clegg } 36493102974SSam Clegg 365*136d27abSRui Ueyama checkGlobalType(s, file, &global->getType()); 366e3498ec5SRui Ueyama 367*136d27abSRui Ueyama if (shouldReplace(s, file, flags)) 368*136d27abSRui Ueyama replaceSym(); 369*136d27abSRui Ueyama return s; 370e3498ec5SRui Ueyama } 371e3498ec5SRui Ueyama 372*136d27abSRui Ueyama Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags, 373*136d27abSRui Ueyama InputFile *file, InputEvent *event) { 374*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addDefinedEvent:" << name << "\n"); 375e915a71fSHeejin Ahn 376*136d27abSRui Ueyama Symbol *s; 377*136d27abSRui Ueyama bool wasInserted; 378*136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 379e915a71fSHeejin Ahn 380*136d27abSRui Ueyama auto replaceSym = [&]() { 381*136d27abSRui Ueyama replaceSymbol<DefinedEvent>(s, name, flags, file, event); 3826540e570SSam Clegg }; 3836540e570SSam Clegg 384*136d27abSRui Ueyama if (wasInserted || s->isLazy()) { 385*136d27abSRui Ueyama replaceSym(); 386*136d27abSRui Ueyama return s; 387e915a71fSHeejin Ahn } 388e915a71fSHeejin Ahn 389*136d27abSRui Ueyama checkEventType(s, file, &event->getType(), &event->signature); 390e915a71fSHeejin Ahn 391*136d27abSRui Ueyama if (shouldReplace(s, file, flags)) 392*136d27abSRui Ueyama replaceSym(); 393*136d27abSRui Ueyama return s; 394e915a71fSHeejin Ahn } 395e915a71fSHeejin Ahn 396*136d27abSRui Ueyama Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName, 397*136d27abSRui Ueyama StringRef importModule, 398*136d27abSRui Ueyama uint32_t flags, InputFile *file, 399*136d27abSRui Ueyama const WasmSignature *sig, 400*136d27abSRui Ueyama bool isCalledDirectly) { 401*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << name << " [" 402*136d27abSRui Ueyama << (sig ? toString(*sig) : "none") 403*136d27abSRui Ueyama << "] IsCalledDirectly:" << isCalledDirectly << "\n"); 404c03c9040SRui Ueyama 405*136d27abSRui Ueyama Symbol *s; 406*136d27abSRui Ueyama bool wasInserted; 407*136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 408*136d27abSRui Ueyama if (s->traced) 409*136d27abSRui Ueyama printTraceSymbolUndefined(name, file); 410c729c1b4SSam Clegg 411*136d27abSRui Ueyama auto replaceSym = [&]() { 412*136d27abSRui Ueyama replaceSymbol<UndefinedFunction>(s, name, importName, importModule, flags, 413*136d27abSRui Ueyama file, sig, isCalledDirectly); 4146540e570SSam Clegg }; 4156540e570SSam Clegg 416*136d27abSRui Ueyama if (wasInserted) 417*136d27abSRui Ueyama replaceSym(); 418*136d27abSRui Ueyama else if (auto *lazy = dyn_cast<LazySymbol>(s)) 419*136d27abSRui Ueyama lazy->fetch(); 4206540e570SSam Clegg else { 421*136d27abSRui Ueyama auto existingFunction = dyn_cast<FunctionSymbol>(s); 422*136d27abSRui Ueyama if (!existingFunction) { 423*136d27abSRui Ueyama reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); 424*136d27abSRui Ueyama return s; 4256540e570SSam Clegg } 426*136d27abSRui Ueyama if (!existingFunction->signature && sig) 427*136d27abSRui Ueyama existingFunction->signature = sig; 428*136d27abSRui Ueyama if (isCalledDirectly && !signatureMatches(existingFunction, sig)) 429*136d27abSRui Ueyama if (getFunctionVariant(s, sig, file, &s)) 430*136d27abSRui Ueyama replaceSym(); 4316540e570SSam Clegg } 432cefbf9acSSam Clegg 433*136d27abSRui Ueyama return s; 434c03c9040SRui Ueyama } 435c03c9040SRui Ueyama 436*136d27abSRui Ueyama Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags, 437*136d27abSRui Ueyama InputFile *file) { 438*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addUndefinedData: " << name << "\n"); 43993102974SSam Clegg 440*136d27abSRui Ueyama Symbol *s; 441*136d27abSRui Ueyama bool wasInserted; 442*136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 443*136d27abSRui Ueyama if (s->traced) 444*136d27abSRui Ueyama printTraceSymbolUndefined(name, file); 445f989a92dSSam Clegg 446*136d27abSRui Ueyama if (wasInserted) 447*136d27abSRui Ueyama replaceSymbol<UndefinedData>(s, name, flags, file); 448*136d27abSRui Ueyama else if (auto *lazy = dyn_cast<LazySymbol>(s)) 449*136d27abSRui Ueyama lazy->fetch(); 450*136d27abSRui Ueyama else if (s->isDefined()) 451*136d27abSRui Ueyama checkDataType(s, file); 452*136d27abSRui Ueyama return s; 453c94d393aSSam Clegg } 454c94d393aSSam Clegg 455*136d27abSRui Ueyama Symbol *SymbolTable::addUndefinedGlobal(StringRef name, StringRef importName, 456*136d27abSRui Ueyama StringRef importModule, uint32_t flags, 457*136d27abSRui Ueyama InputFile *file, 458*136d27abSRui Ueyama const WasmGlobalType *type) { 459*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n"); 460e3498ec5SRui Ueyama 461*136d27abSRui Ueyama Symbol *s; 462*136d27abSRui Ueyama bool wasInserted; 463*136d27abSRui Ueyama std::tie(s, wasInserted) = insert(name, file); 464*136d27abSRui Ueyama if (s->traced) 465*136d27abSRui Ueyama printTraceSymbolUndefined(name, file); 466c729c1b4SSam Clegg 467*136d27abSRui Ueyama if (wasInserted) 468*136d27abSRui Ueyama replaceSymbol<UndefinedGlobal>(s, name, importName, importModule, flags, 469*136d27abSRui Ueyama file, type); 470*136d27abSRui Ueyama else if (auto *lazy = dyn_cast<LazySymbol>(s)) 471*136d27abSRui Ueyama lazy->fetch(); 472*136d27abSRui Ueyama else if (s->isDefined()) 473*136d27abSRui Ueyama checkGlobalType(s, file, type); 474*136d27abSRui Ueyama return s; 475e3498ec5SRui Ueyama } 476e3498ec5SRui Ueyama 477*136d27abSRui Ueyama void SymbolTable::addLazy(ArchiveFile *file, const Archive::Symbol *sym) { 478*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "addLazy: " << sym->getName() << "\n"); 479*136d27abSRui Ueyama StringRef name = sym->getName(); 480c03c9040SRui Ueyama 481*136d27abSRui Ueyama Symbol *s; 482*136d27abSRui Ueyama bool wasInserted; 483*136d27abSRui Ueyama std::tie(s, wasInserted) = insertName(name); 484c03c9040SRui Ueyama 485*136d27abSRui Ueyama if (wasInserted) { 486*136d27abSRui Ueyama replaceSymbol<LazySymbol>(s, name, 0, file, *sym); 487c03c9040SRui Ueyama return; 488c03c9040SRui Ueyama } 489c03c9040SRui Ueyama 490*136d27abSRui Ueyama if (!s->isUndefined()) 49137b4ee52SSam Clegg return; 49237b4ee52SSam Clegg 49337b4ee52SSam Clegg // The existing symbol is undefined, load a new one from the archive, 49437b4ee52SSam Clegg // unless the the existing symbol is weak in which case replace the undefined 49537b4ee52SSam Clegg // symbols with a LazySymbol. 496*136d27abSRui Ueyama if (s->isWeak()) { 497*136d27abSRui Ueyama const WasmSignature *oldSig = nullptr; 49837b4ee52SSam Clegg // In the case of an UndefinedFunction we need to preserve the expected 49937b4ee52SSam Clegg // signature. 500*136d27abSRui Ueyama if (auto *f = dyn_cast<UndefinedFunction>(s)) 501*136d27abSRui Ueyama oldSig = f->signature; 50237b4ee52SSam Clegg LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); 503*136d27abSRui Ueyama auto newSym = replaceSymbol<LazySymbol>(s, name, WASM_SYMBOL_BINDING_WEAK, 504*136d27abSRui Ueyama file, *sym); 505*136d27abSRui Ueyama newSym->signature = oldSig; 50637b4ee52SSam Clegg return; 50737b4ee52SSam Clegg } 50837b4ee52SSam Clegg 509e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 510*136d27abSRui Ueyama file->addMember(sym); 511c94d393aSSam Clegg } 512e0f6fcd0SSam Clegg 513*136d27abSRui Ueyama bool SymbolTable::addComdat(StringRef name) { 514*136d27abSRui Ueyama return comdatGroups.insert(CachedHashStringRef(name)).second; 515e0f6fcd0SSam Clegg } 5161f3f774fSSam Clegg 5176540e570SSam Clegg // The new signature doesn't match. Create a variant to the symbol with the 5186540e570SSam Clegg // signature encoded in the name and return that instead. These symbols are 5196540e570SSam Clegg // then unified later in handleSymbolVariants. 520*136d27abSRui Ueyama bool SymbolTable::getFunctionVariant(Symbol* sym, const WasmSignature *sig, 521*136d27abSRui Ueyama const InputFile *file, Symbol **out) { 522*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "getFunctionVariant: " << sym->getName() << " -> " 523*136d27abSRui Ueyama << " " << toString(*sig) << "\n"); 524*136d27abSRui Ueyama Symbol *variant = nullptr; 5256540e570SSam Clegg 5266540e570SSam Clegg // Linear search through symbol variants. Should never be more than two 5276540e570SSam Clegg // or three entries here. 528*136d27abSRui Ueyama auto &variants = symVariants[CachedHashStringRef(sym->getName())]; 529*136d27abSRui Ueyama if (variants.empty()) 530*136d27abSRui Ueyama variants.push_back(sym); 5316540e570SSam Clegg 532*136d27abSRui Ueyama for (Symbol* v : variants) { 533*136d27abSRui Ueyama if (*v->getSignature() == *sig) { 534*136d27abSRui Ueyama variant = v; 5356540e570SSam Clegg break; 5366540e570SSam Clegg } 5376540e570SSam Clegg } 5386540e570SSam Clegg 539*136d27abSRui Ueyama bool wasAdded = !variant; 540*136d27abSRui Ueyama if (wasAdded) { 5416540e570SSam Clegg // Create a new variant; 5426540e570SSam Clegg LLVM_DEBUG(dbgs() << "added new variant\n"); 543*136d27abSRui Ueyama variant = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 544*136d27abSRui Ueyama variants.push_back(variant); 5456540e570SSam Clegg } else { 546*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*variant) << "\n"); 547*136d27abSRui Ueyama assert(*variant->getSignature() == *sig); 5486540e570SSam Clegg } 5496540e570SSam Clegg 550*136d27abSRui Ueyama *out = variant; 551*136d27abSRui Ueyama return wasAdded; 5526540e570SSam Clegg } 5536540e570SSam Clegg 5541f3f774fSSam Clegg // Set a flag for --trace-symbol so that we can print out a log message 5551f3f774fSSam Clegg // if a new symbol with the same name is inserted into the symbol table. 556*136d27abSRui Ueyama void SymbolTable::trace(StringRef name) { 557*136d27abSRui Ueyama symMap.insert({CachedHashStringRef(name), -1}); 5581f3f774fSSam Clegg } 559230dc11dSSam Clegg 560*136d27abSRui Ueyama void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { 561a5ca34e6SSam Clegg // Swap symbols as instructed by -wrap. 562*136d27abSRui Ueyama int &origIdx = symMap[CachedHashStringRef(sym->getName())]; 563*136d27abSRui Ueyama int &realIdx= symMap[CachedHashStringRef(real->getName())]; 564*136d27abSRui Ueyama int &wrapIdx = symMap[CachedHashStringRef(wrap->getName())]; 565*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "wrap: " << sym->getName() << "\n"); 566a5ca34e6SSam Clegg 567a5ca34e6SSam Clegg // Anyone looking up __real symbols should get the original 568*136d27abSRui Ueyama realIdx = origIdx; 569a5ca34e6SSam Clegg // Anyone looking up the original should get the __wrap symbol 570*136d27abSRui Ueyama origIdx = wrapIdx; 571a5ca34e6SSam Clegg } 572a5ca34e6SSam Clegg 573*136d27abSRui Ueyama static const uint8_t unreachableFn[] = { 574230dc11dSSam Clegg 0x03 /* ULEB length */, 0x00 /* ULEB num locals */, 575230dc11dSSam Clegg 0x00 /* opcode unreachable */, 0x0b /* opcode end */ 576230dc11dSSam Clegg }; 577230dc11dSSam Clegg 578230dc11dSSam Clegg // Replace the given symbol body with an unreachable function. 579230dc11dSSam Clegg // This is used by handleWeakUndefines in order to generate a callable 5806540e570SSam Clegg // equivalent of an undefined function and also handleSymbolVariants for 5816540e570SSam Clegg // undefined functions that don't match the signature of the definition. 582*136d27abSRui Ueyama InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym, 583*136d27abSRui Ueyama const WasmSignature &sig, 584*136d27abSRui Ueyama StringRef debugName) { 585*136d27abSRui Ueyama auto *func = make<SyntheticFunction>(sig, sym->getName(), debugName); 586*136d27abSRui Ueyama func->setBody(unreachableFn); 587*136d27abSRui Ueyama syntheticFunctions.emplace_back(func); 588*136d27abSRui Ueyama replaceSymbol<DefinedFunction>(sym, sym->getName(), sym->getFlags(), nullptr, 589*136d27abSRui Ueyama func); 590*136d27abSRui Ueyama return func; 591230dc11dSSam Clegg } 592230dc11dSSam Clegg 593230dc11dSSam Clegg // For weak undefined functions, there may be "call" instructions that reference 594230dc11dSSam Clegg // the symbol. In this case, we need to synthesise a dummy/stub function that 595230dc11dSSam Clegg // will abort at runtime, so that relocations can still provided an operand to 596230dc11dSSam Clegg // the call instruction that passes Wasm validation. 597230dc11dSSam Clegg void SymbolTable::handleWeakUndefines() { 598*136d27abSRui Ueyama for (Symbol *sym : getSymbols()) { 599*136d27abSRui Ueyama if (!sym->isUndefWeak()) 600230dc11dSSam Clegg continue; 601230dc11dSSam Clegg 602*136d27abSRui Ueyama const WasmSignature *sig = sym->getSignature(); 603*136d27abSRui Ueyama if (!sig) { 604230dc11dSSam Clegg // It is possible for undefined functions not to have a signature (eg. if 605230dc11dSSam Clegg // added via "--undefined"), but weak undefined ones do have a signature. 6066540e570SSam Clegg // Lazy symbols may not be functions and therefore Sig can still be null 6076540e570SSam Clegg // in some circumstantce. 608*136d27abSRui Ueyama assert(!isa<FunctionSymbol>(sym)); 609230dc11dSSam Clegg continue; 6106540e570SSam Clegg } 611230dc11dSSam Clegg 612230dc11dSSam Clegg // Add a synthetic dummy for weak undefined functions. These dummies will 613230dc11dSSam Clegg // be GC'd if not used as the target of any "call" instructions. 614*136d27abSRui Ueyama StringRef debugName = saver.save("undefined:" + toString(*sym)); 615*136d27abSRui Ueyama InputFunction* func = replaceWithUnreachable(sym, *sig, debugName); 616230dc11dSSam Clegg // Ensure it compares equal to the null pointer, and so that table relocs 617230dc11dSSam Clegg // don't pull in the stub body (only call-operand relocs should do that). 618*136d27abSRui Ueyama func->setTableIndex(0); 619230dc11dSSam Clegg // Hide our dummy to prevent export. 620*136d27abSRui Ueyama sym->setHidden(true); 621230dc11dSSam Clegg } 622230dc11dSSam Clegg } 6236540e570SSam Clegg 624*136d27abSRui Ueyama static void reportFunctionSignatureMismatch(StringRef symName, 625*136d27abSRui Ueyama FunctionSymbol *a, 626*136d27abSRui Ueyama FunctionSymbol *b, bool isError) { 627*136d27abSRui Ueyama std::string msg = ("function signature mismatch: " + symName + 628*136d27abSRui Ueyama "\n>>> defined as " + toString(*a->signature) + " in " + 629*136d27abSRui Ueyama toString(a->getFile()) + "\n>>> defined as " + 630*136d27abSRui Ueyama toString(*b->signature) + " in " + toString(b->getFile())) 6316540e570SSam Clegg .str(); 632*136d27abSRui Ueyama if (isError) 6336540e570SSam Clegg error(msg); 6346540e570SSam Clegg else 6356540e570SSam Clegg warn(msg); 6366540e570SSam Clegg } 6376540e570SSam Clegg 6386540e570SSam Clegg // Remove any variant symbols that were created due to function signature 6396540e570SSam Clegg // mismatches. 6406540e570SSam Clegg void SymbolTable::handleSymbolVariants() { 641*136d27abSRui Ueyama for (auto pair : symVariants) { 6426540e570SSam Clegg // Push the initial symbol onto the list of variants. 643*136d27abSRui Ueyama StringRef symName = pair.first.val(); 644*136d27abSRui Ueyama std::vector<Symbol *> &variants = pair.second; 6456540e570SSam Clegg 6466540e570SSam Clegg #ifndef NDEBUG 647*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << "symbol with (" << variants.size() 648*136d27abSRui Ueyama << ") variants: " << symName << "\n"); 649*136d27abSRui Ueyama for (auto *s: variants) { 650*136d27abSRui Ueyama auto *f = cast<FunctionSymbol>(s); 651*136d27abSRui Ueyama LLVM_DEBUG(dbgs() << " variant: " + f->getName() << " " 652*136d27abSRui Ueyama << toString(*f->signature) << "\n"); 6536540e570SSam Clegg } 6546540e570SSam Clegg #endif 6556540e570SSam Clegg 6566540e570SSam Clegg // Find the one definition. 657*136d27abSRui Ueyama DefinedFunction *defined = nullptr; 658*136d27abSRui Ueyama for (auto *symbol : variants) { 659*136d27abSRui Ueyama if (auto f = dyn_cast<DefinedFunction>(symbol)) { 660*136d27abSRui Ueyama defined = f; 6616540e570SSam Clegg break; 6626540e570SSam Clegg } 6636540e570SSam Clegg } 6646540e570SSam Clegg 6656540e570SSam Clegg // If there are no definitions, and the undefined symbols disagree on 6666540e570SSam Clegg // the signature, there is not we can do since we don't know which one 6676540e570SSam Clegg // to use as the signature on the import. 668*136d27abSRui Ueyama if (!defined) { 669*136d27abSRui Ueyama reportFunctionSignatureMismatch(symName, 670*136d27abSRui Ueyama cast<FunctionSymbol>(variants[0]), 671*136d27abSRui Ueyama cast<FunctionSymbol>(variants[1]), true); 6726540e570SSam Clegg return; 6736540e570SSam Clegg } 6746540e570SSam Clegg 675*136d27abSRui Ueyama for (auto *symbol : variants) { 676*136d27abSRui Ueyama if (symbol != defined) { 677*136d27abSRui Ueyama auto *f = cast<FunctionSymbol>(symbol); 678*136d27abSRui Ueyama reportFunctionSignatureMismatch(symName, f, defined, false); 679*136d27abSRui Ueyama StringRef debugName = saver.save("unreachable:" + toString(*f)); 680*136d27abSRui Ueyama replaceWithUnreachable(f, *f->signature, debugName); 6816540e570SSam Clegg } 6826540e570SSam Clegg } 6836540e570SSam Clegg } 6846540e570SSam Clegg } 685