1c94d393aSSam Clegg //===- SymbolTable.cpp ----------------------------------------------------===// 2c94d393aSSam Clegg // 3c94d393aSSam Clegg // The LLVM Linker 4c94d393aSSam Clegg // 5c94d393aSSam Clegg // This file is distributed under the University of Illinois Open Source 6c94d393aSSam Clegg // License. See LICENSE.TXT for details. 7c94d393aSSam Clegg // 8c94d393aSSam Clegg //===----------------------------------------------------------------------===// 9c94d393aSSam Clegg 10c94d393aSSam Clegg #include "SymbolTable.h" 11c94d393aSSam Clegg #include "Config.h" 125fa274beSSam Clegg #include "InputChunks.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; 23*45218f4aSSam Clegg using namespace llvm::object; 24c94d393aSSam Clegg using namespace lld; 25c94d393aSSam Clegg using namespace lld::wasm; 26c94d393aSSam Clegg 27c94d393aSSam Clegg SymbolTable *lld::wasm::Symtab; 28c94d393aSSam Clegg 29c94d393aSSam Clegg void SymbolTable::addFile(InputFile *File) { 30c94d393aSSam Clegg log("Processing: " + toString(File)); 31c94d393aSSam Clegg File->parse(); 32c94d393aSSam Clegg 33c729c1b4SSam Clegg // LLVM bitcode file 34c729c1b4SSam Clegg if (auto *F = dyn_cast<BitcodeFile>(File)) 35c729c1b4SSam Clegg BitcodeFiles.push_back(F); 36c729c1b4SSam Clegg else if (auto *F = dyn_cast<ObjFile>(File)) 37c94d393aSSam Clegg ObjectFiles.push_back(F); 38c94d393aSSam Clegg } 39c94d393aSSam Clegg 40c729c1b4SSam Clegg // This function is where all the optimizations of link-time 41c729c1b4SSam Clegg // optimization happens. When LTO is in use, some input files are 42c729c1b4SSam Clegg // not in native object file format but in the LLVM bitcode format. 43c729c1b4SSam Clegg // This function compiles bitcode files into a few big native files 44c729c1b4SSam Clegg // using LLVM functions and replaces bitcode symbols with the results. 45c729c1b4SSam Clegg // Because all bitcode files that the program consists of are passed 46c729c1b4SSam Clegg // to the compiler at once, it can do whole-program optimization. 47c729c1b4SSam Clegg void SymbolTable::addCombinedLTOObject() { 48c729c1b4SSam Clegg if (BitcodeFiles.empty()) 49c729c1b4SSam Clegg return; 50c729c1b4SSam Clegg 51c729c1b4SSam Clegg // Compile bitcode files and replace bitcode symbols. 52c729c1b4SSam Clegg LTO.reset(new BitcodeCompiler); 53c729c1b4SSam Clegg for (BitcodeFile *F : BitcodeFiles) 54c729c1b4SSam Clegg LTO->add(*F); 55c729c1b4SSam Clegg 56c729c1b4SSam Clegg for (StringRef Filename : LTO->compile()) { 57c729c1b4SSam Clegg auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp")); 58c729c1b4SSam Clegg Obj->parse(); 59c729c1b4SSam Clegg ObjectFiles.push_back(Obj); 60c729c1b4SSam Clegg } 61c729c1b4SSam Clegg } 62c729c1b4SSam Clegg 63c94d393aSSam Clegg void SymbolTable::reportRemainingUndefines() { 6474fe0ba1SSam Clegg for (Symbol *Sym : SymVector) { 65c729c1b4SSam Clegg if (!Sym->isUndefined() || Sym->isWeak()) 66c729c1b4SSam Clegg continue; 67c729c1b4SSam Clegg if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0) 68c729c1b4SSam Clegg continue; 69c729c1b4SSam Clegg if (!Sym->IsUsedInRegularObj) 70c729c1b4SSam Clegg continue; 7147e2b6b2SSam Clegg error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); 72c94d393aSSam Clegg } 73c94d393aSSam Clegg } 74c94d393aSSam Clegg 75c94d393aSSam Clegg Symbol *SymbolTable::find(StringRef Name) { 7667d6908fSRui Ueyama return SymMap.lookup(CachedHashStringRef(Name)); 77c94d393aSSam Clegg } 78c94d393aSSam Clegg 794c2cbfe6SSam Clegg std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) { 804c2cbfe6SSam Clegg bool Inserted = false; 81a80d94d5SSam Clegg Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; 824c2cbfe6SSam Clegg if (!Sym) { 83dfb0b2c7SSam Clegg Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 84c729c1b4SSam Clegg Sym->IsUsedInRegularObj = false; 8574fe0ba1SSam Clegg SymVector.emplace_back(Sym); 864c2cbfe6SSam Clegg Inserted = true; 874c2cbfe6SSam Clegg } 884c2cbfe6SSam Clegg if (!File || File->kind() == InputFile::ObjectKind) 894c2cbfe6SSam Clegg Sym->IsUsedInRegularObj = true; 904c2cbfe6SSam Clegg return {Sym, Inserted}; 91c94d393aSSam Clegg } 92c94d393aSSam Clegg 93e3498ec5SRui Ueyama static void reportTypeError(const Symbol *Existing, const InputFile *File, 943876d89aSSam Clegg llvm::wasm::WasmSymbolType Type) { 95e3498ec5SRui Ueyama error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + 96e3498ec5SRui Ueyama toString(Existing->getWasmType()) + " in " + 973876d89aSSam Clegg toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + 983876d89aSSam Clegg " in " + toString(File)); 99e3498ec5SRui Ueyama } 100e3498ec5SRui Ueyama 1016f4286fbSHeejin Ahn // Check the type of new symbol matches that of the symbol is replacing. 1026f4286fbSHeejin Ahn // For functions this can also involve verifying that the signatures match. 103cefbf9acSSam Clegg static void checkFunctionType(Symbol *Existing, const InputFile *File, 104e3498ec5SRui Ueyama const WasmSignature *NewSig) { 10565d6380cSSam Clegg auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing); 10665d6380cSSam Clegg if (!ExistingFunction) { 1073876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION); 108e3498ec5SRui Ueyama return; 109e3498ec5SRui Ueyama } 110e3498ec5SRui Ueyama 111cefbf9acSSam Clegg if (!NewSig) 112cefbf9acSSam Clegg return; 113cefbf9acSSam Clegg 114cefbf9acSSam Clegg const WasmSignature *OldSig = ExistingFunction->FunctionType; 115cefbf9acSSam Clegg if (!OldSig) { 116cefbf9acSSam Clegg ExistingFunction->FunctionType = NewSig; 117cefbf9acSSam Clegg return; 118cefbf9acSSam Clegg } 119cefbf9acSSam Clegg 120cefbf9acSSam Clegg if (*NewSig != *OldSig) 121ffd0aaf8SSam Clegg warn("function signature mismatch: " + Existing->getName() + 122e3498ec5SRui Ueyama "\n>>> defined as " + toString(*OldSig) + " in " + 123e3498ec5SRui Ueyama toString(Existing->getFile()) + "\n>>> defined as " + 124ffd0aaf8SSam Clegg toString(*NewSig) + " in " + toString(File)); 125e3498ec5SRui Ueyama } 126e3498ec5SRui Ueyama 127e3498ec5SRui Ueyama static void checkGlobalType(const Symbol *Existing, const InputFile *File, 128e3498ec5SRui Ueyama const WasmGlobalType *NewType) { 129e3498ec5SRui Ueyama if (!isa<GlobalSymbol>(Existing)) { 1303876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); 131b8621596SSam Clegg return; 132b8621596SSam Clegg } 133b8621596SSam Clegg 134e3498ec5SRui Ueyama const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType(); 135e3498ec5SRui Ueyama if (*NewType != *OldType) { 136e3498ec5SRui Ueyama error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + 137e3498ec5SRui Ueyama toString(*OldType) + " in " + toString(Existing->getFile()) + 138e3498ec5SRui Ueyama "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 139c94d393aSSam Clegg } 14024b3dcd4SSam Clegg } 14124b3dcd4SSam Clegg 142e3498ec5SRui Ueyama static void checkDataType(const Symbol *Existing, const InputFile *File) { 143e3498ec5SRui Ueyama if (!isa<DataSymbol>(Existing)) 1443876d89aSSam Clegg reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); 145e3498ec5SRui Ueyama } 146e3498ec5SRui Ueyama 147dfb0b2c7SSam Clegg DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, 148ebda41f8SNicholas Wilson uint32_t Flags, 149ebda41f8SNicholas Wilson InputFunction *Function) { 150e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); 151b961abc8SRui Ueyama assert(!find(Name)); 152ebda41f8SNicholas Wilson SyntheticFunctions.emplace_back(Function); 1534c2cbfe6SSam Clegg return replaceSymbol<DefinedFunction>(insert(Name, nullptr).first, Name, 1544c2cbfe6SSam Clegg Flags, nullptr, Function); 15550686856SSam Clegg } 15650686856SSam Clegg 15700245539SSam Clegg DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, 15800245539SSam Clegg uint32_t Flags) { 159e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); 160b961abc8SRui Ueyama assert(!find(Name)); 1614c2cbfe6SSam Clegg return replaceSymbol<DefinedData>(insert(Name, nullptr).first, Name, Flags); 162c94d393aSSam Clegg } 163c94d393aSSam Clegg 16493102974SSam Clegg DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, 16593102974SSam Clegg InputGlobal *Global) { 166e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global 167e7245b42SNicola Zaghen << "\n"); 168b961abc8SRui Ueyama assert(!find(Name)); 169ebda41f8SNicholas Wilson SyntheticGlobals.emplace_back(Global); 1704c2cbfe6SSam Clegg return replaceSymbol<DefinedGlobal>(insert(Name, nullptr).first, Name, Flags, 1714c2cbfe6SSam Clegg nullptr, Global); 17293102974SSam Clegg } 17393102974SSam Clegg 174e3498ec5SRui Ueyama static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, 175e3498ec5SRui Ueyama uint32_t NewFlags) { 176c03c9040SRui Ueyama // If existing symbol is undefined, replace it. 177e3498ec5SRui Ueyama if (!Existing->isDefined()) { 178e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 179e3498ec5SRui Ueyama << Existing->getName() << "\n"); 180c03c9040SRui Ueyama return true; 181c03c9040SRui Ueyama } 182c03c9040SRui Ueyama 183c03c9040SRui Ueyama // Now we have two defined symbols. If the new one is weak, we can ignore it. 184c03c9040SRui Ueyama if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 185e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 186c03c9040SRui Ueyama return false; 187c03c9040SRui Ueyama } 188c03c9040SRui Ueyama 189c03c9040SRui Ueyama // If the existing symbol is weak, we should replace it. 190e3498ec5SRui Ueyama if (Existing->isWeak()) { 191e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 192c03c9040SRui Ueyama return true; 193c03c9040SRui Ueyama } 194c03c9040SRui Ueyama 195c03c9040SRui Ueyama // Neither symbol is week. They conflict. 196e3498ec5SRui Ueyama error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + 197e3498ec5SRui Ueyama toString(Existing->getFile()) + "\n>>> defined in " + 198e3498ec5SRui Ueyama toString(NewFile)); 199c03c9040SRui Ueyama return true; 200b8621596SSam Clegg } 20193e559b1SSam Clegg 20293e559b1SSam Clegg Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, 203e3498ec5SRui Ueyama InputFile *File, 204e3498ec5SRui Ueyama InputFunction *Function) { 2058b0b48f3SSam Clegg LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" 2068b0b48f3SSam Clegg << (Function ? toString(Function->Signature) : "none") 2078b0b48f3SSam Clegg << "]\n"); 20893e559b1SSam Clegg Symbol *S; 20993e559b1SSam Clegg bool WasInserted; 2104c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 211c729c1b4SSam Clegg 212e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 213e3498ec5SRui Ueyama replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 214e3498ec5SRui Ueyama return S; 215e3498ec5SRui Ueyama } 216e3498ec5SRui Ueyama 217c729c1b4SSam Clegg if (Function) 218e3498ec5SRui Ueyama checkFunctionType(S, File, &Function->Signature); 219e3498ec5SRui Ueyama 2208b0b48f3SSam Clegg if (shouldReplace(S, File, Flags)) { 2218b0b48f3SSam Clegg // If the new defined function doesn't have signture (i.e. bitcode 2228b0b48f3SSam Clegg // functions) but the old symbols does then preserve the old signature 2238b0b48f3SSam Clegg const WasmSignature *OldSig = nullptr; 2248b0b48f3SSam Clegg if (auto* F = dyn_cast<FunctionSymbol>(S)) 2258b0b48f3SSam Clegg OldSig = F->FunctionType; 2268b0b48f3SSam Clegg auto NewSym = replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 2278b0b48f3SSam Clegg if (!NewSym->FunctionType) 2288b0b48f3SSam Clegg NewSym->FunctionType = OldSig; 2298b0b48f3SSam Clegg } 23093e559b1SSam Clegg return S; 23193e559b1SSam Clegg } 23293e559b1SSam Clegg 23300245539SSam Clegg Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, 234e3498ec5SRui Ueyama InputFile *File, InputSegment *Segment, 23593102974SSam Clegg uint32_t Address, uint32_t Size) { 236e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address 237e7245b42SNicola Zaghen << "\n"); 23893e559b1SSam Clegg Symbol *S; 23993e559b1SSam Clegg bool WasInserted; 2404c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 241c729c1b4SSam Clegg 242e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 243e3498ec5SRui Ueyama replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 244e3498ec5SRui Ueyama return S; 245e3498ec5SRui Ueyama } 246e3498ec5SRui Ueyama 247e3498ec5SRui Ueyama checkDataType(S, File); 248e3498ec5SRui Ueyama 249e3498ec5SRui Ueyama if (shouldReplace(S, File, Flags)) 250e3498ec5SRui Ueyama replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 251c94d393aSSam Clegg return S; 252c94d393aSSam Clegg } 253c94d393aSSam Clegg 25493102974SSam Clegg Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, 255e3498ec5SRui Ueyama InputFile *File, InputGlobal *Global) { 256e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); 2574c2cbfe6SSam Clegg 25893102974SSam Clegg Symbol *S; 25993102974SSam Clegg bool WasInserted; 2604c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 261c729c1b4SSam Clegg 262e3498ec5SRui Ueyama if (WasInserted || S->isLazy()) { 263e3498ec5SRui Ueyama replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 26493102974SSam Clegg return S; 26593102974SSam Clegg } 26693102974SSam Clegg 267e3498ec5SRui Ueyama checkGlobalType(S, File, &Global->getType()); 268e3498ec5SRui Ueyama 269e3498ec5SRui Ueyama if (shouldReplace(S, File, Flags)) 270e3498ec5SRui Ueyama replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 271e3498ec5SRui Ueyama return S; 272e3498ec5SRui Ueyama } 273e3498ec5SRui Ueyama 274e3498ec5SRui Ueyama Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags, 275e3498ec5SRui Ueyama InputFile *File, 276e3498ec5SRui Ueyama const WasmSignature *Sig) { 2778b0b48f3SSam Clegg LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << 2788b0b48f3SSam Clegg " [" << (Sig ? toString(*Sig) : "none") << "]\n"); 279c03c9040SRui Ueyama 280c94d393aSSam Clegg Symbol *S; 281c94d393aSSam Clegg bool WasInserted; 2824c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 283c729c1b4SSam Clegg 284e3498ec5SRui Ueyama if (WasInserted) 285e3498ec5SRui Ueyama replaceSymbol<UndefinedFunction>(S, Name, Flags, File, Sig); 286e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 287b961abc8SRui Ueyama Lazy->fetch(); 288cefbf9acSSam Clegg else 289e3498ec5SRui Ueyama checkFunctionType(S, File, Sig); 290cefbf9acSSam Clegg 291c03c9040SRui Ueyama return S; 292c03c9040SRui Ueyama } 293c03c9040SRui Ueyama 294e3498ec5SRui Ueyama Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, 295e3498ec5SRui Ueyama InputFile *File) { 296e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); 29793102974SSam Clegg 298e3498ec5SRui Ueyama Symbol *S; 299e3498ec5SRui Ueyama bool WasInserted; 3004c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 301f989a92dSSam Clegg 302e3498ec5SRui Ueyama if (WasInserted) 303e3498ec5SRui Ueyama replaceSymbol<UndefinedData>(S, Name, Flags, File); 304e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 305b961abc8SRui Ueyama Lazy->fetch(); 306e3498ec5SRui Ueyama else if (S->isDefined()) 307e3498ec5SRui Ueyama checkDataType(S, File); 308c94d393aSSam Clegg return S; 309c94d393aSSam Clegg } 310c94d393aSSam Clegg 311e3498ec5SRui Ueyama Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags, 312e3498ec5SRui Ueyama InputFile *File, 313e3498ec5SRui Ueyama const WasmGlobalType *Type) { 314e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); 315e3498ec5SRui Ueyama 316e3498ec5SRui Ueyama Symbol *S; 317e3498ec5SRui Ueyama bool WasInserted; 3184c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, File); 319c729c1b4SSam Clegg 320e3498ec5SRui Ueyama if (WasInserted) 321e3498ec5SRui Ueyama replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type); 322e3498ec5SRui Ueyama else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 323b961abc8SRui Ueyama Lazy->fetch(); 324e3498ec5SRui Ueyama else if (S->isDefined()) 325e3498ec5SRui Ueyama checkGlobalType(S, File, Type); 326e3498ec5SRui Ueyama return S; 327e3498ec5SRui Ueyama } 328e3498ec5SRui Ueyama 329e3498ec5SRui Ueyama void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { 330e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); 331c94d393aSSam Clegg StringRef Name = Sym->getName(); 332c03c9040SRui Ueyama 333c94d393aSSam Clegg Symbol *S; 334c94d393aSSam Clegg bool WasInserted; 3354c2cbfe6SSam Clegg std::tie(S, WasInserted) = insert(Name, nullptr); 336c03c9040SRui Ueyama 337c94d393aSSam Clegg if (WasInserted) { 338e3498ec5SRui Ueyama replaceSymbol<LazySymbol>(S, Name, File, *Sym); 339c03c9040SRui Ueyama return; 340c03c9040SRui Ueyama } 341c03c9040SRui Ueyama 342c03c9040SRui Ueyama // If there is an existing undefined symbol, load a new one from the archive. 343c03c9040SRui Ueyama if (S->isUndefined()) { 344e7245b42SNicola Zaghen LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 345e3498ec5SRui Ueyama File->addMember(Sym); 346c94d393aSSam Clegg } 347c94d393aSSam Clegg } 348e0f6fcd0SSam Clegg 349c4d9aa1bSNicholas Wilson bool SymbolTable::addComdat(StringRef Name) { 350c4d9aa1bSNicholas Wilson return Comdats.insert(CachedHashStringRef(Name)).second; 351e0f6fcd0SSam Clegg } 352