1 //===- SymbolTable.cpp ----------------------------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "SymbolTable.h" 11 #include "Config.h" 12 #include "InputChunks.h" 13 #include "InputGlobal.h" 14 #include "WriterUtils.h" 15 #include "lld/Common/ErrorHandler.h" 16 #include "lld/Common/Memory.h" 17 #include "llvm/ADT/SetVector.h" 18 19 #define DEBUG_TYPE "lld" 20 21 using namespace llvm; 22 using namespace llvm::wasm; 23 using namespace lld; 24 using namespace lld::wasm; 25 26 SymbolTable *lld::wasm::Symtab; 27 28 void SymbolTable::addFile(InputFile *File) { 29 log("Processing: " + toString(File)); 30 File->parse(); 31 32 // LLVM bitcode file 33 if (auto *F = dyn_cast<BitcodeFile>(File)) 34 BitcodeFiles.push_back(F); 35 else if (auto *F = dyn_cast<ObjFile>(File)) 36 ObjectFiles.push_back(F); 37 } 38 39 // This function is where all the optimizations of link-time 40 // optimization happens. When LTO is in use, some input files are 41 // not in native object file format but in the LLVM bitcode format. 42 // This function compiles bitcode files into a few big native files 43 // using LLVM functions and replaces bitcode symbols with the results. 44 // Because all bitcode files that the program consists of are passed 45 // to the compiler at once, it can do whole-program optimization. 46 void SymbolTable::addCombinedLTOObject() { 47 if (BitcodeFiles.empty()) 48 return; 49 50 // Compile bitcode files and replace bitcode symbols. 51 LTO.reset(new BitcodeCompiler); 52 for (BitcodeFile *F : BitcodeFiles) 53 LTO->add(*F); 54 55 for (StringRef Filename : LTO->compile()) { 56 auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp")); 57 Obj->parse(); 58 ObjectFiles.push_back(Obj); 59 } 60 } 61 62 void SymbolTable::reportRemainingUndefines() { 63 for (Symbol *Sym : SymVector) { 64 if (!Sym->isUndefined() || Sym->isWeak()) 65 continue; 66 if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0) 67 continue; 68 if (!Sym->IsUsedInRegularObj) 69 continue; 70 error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); 71 } 72 } 73 74 Symbol *SymbolTable::find(StringRef Name) { 75 return SymMap.lookup(CachedHashStringRef(Name)); 76 } 77 78 std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) { 79 bool Inserted = false; 80 Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; 81 if (!Sym) { 82 Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 83 Sym->IsUsedInRegularObj = false; 84 SymVector.emplace_back(Sym); 85 Inserted = true; 86 } 87 if (!File || File->kind() == InputFile::ObjectKind) 88 Sym->IsUsedInRegularObj = true; 89 return {Sym, Inserted}; 90 } 91 92 static void reportTypeError(const Symbol *Existing, const InputFile *File, 93 llvm::wasm::WasmSymbolType Type) { 94 error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + 95 toString(Existing->getWasmType()) + " in " + 96 toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + 97 " in " + toString(File)); 98 } 99 100 static void checkFunctionType(Symbol *Existing, const InputFile *File, 101 const WasmSignature *NewSig) { 102 auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing); 103 if (!ExistingFunction) { 104 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION); 105 return; 106 } 107 108 if (!NewSig) 109 return; 110 111 const WasmSignature *OldSig = ExistingFunction->FunctionType; 112 if (!OldSig) { 113 ExistingFunction->FunctionType = NewSig; 114 return; 115 } 116 117 if (*NewSig != *OldSig) 118 warn("function signature mismatch: " + Existing->getName() + 119 "\n>>> defined as " + toString(*OldSig) + " in " + 120 toString(Existing->getFile()) + "\n>>> defined as " + 121 toString(*NewSig) + " in " + toString(File)); 122 } 123 124 // Check the type of new symbol matches that of the symbol is replacing. 125 // For functions this can also involve verifying that the signatures match. 126 static void checkGlobalType(const Symbol *Existing, const InputFile *File, 127 const WasmGlobalType *NewType) { 128 if (!isa<GlobalSymbol>(Existing)) { 129 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); 130 return; 131 } 132 133 const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType(); 134 if (*NewType != *OldType) { 135 error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + 136 toString(*OldType) + " in " + toString(Existing->getFile()) + 137 "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 138 } 139 } 140 141 static void checkDataType(const Symbol *Existing, const InputFile *File) { 142 if (!isa<DataSymbol>(Existing)) 143 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); 144 } 145 146 DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, 147 uint32_t Flags, 148 InputFunction *Function) { 149 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); 150 assert(!find(Name)); 151 SyntheticFunctions.emplace_back(Function); 152 return replaceSymbol<DefinedFunction>(insert(Name, nullptr).first, Name, 153 Flags, nullptr, Function); 154 } 155 156 DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, 157 uint32_t Flags) { 158 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); 159 assert(!find(Name)); 160 return replaceSymbol<DefinedData>(insert(Name, nullptr).first, Name, Flags); 161 } 162 163 DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, 164 InputGlobal *Global) { 165 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global 166 << "\n"); 167 assert(!find(Name)); 168 SyntheticGlobals.emplace_back(Global); 169 return replaceSymbol<DefinedGlobal>(insert(Name, nullptr).first, Name, Flags, 170 nullptr, Global); 171 } 172 173 static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, 174 uint32_t NewFlags) { 175 // If existing symbol is undefined, replace it. 176 if (!Existing->isDefined()) { 177 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 178 << Existing->getName() << "\n"); 179 return true; 180 } 181 182 // Now we have two defined symbols. If the new one is weak, we can ignore it. 183 if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 184 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 185 return false; 186 } 187 188 // If the existing symbol is weak, we should replace it. 189 if (Existing->isWeak()) { 190 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 191 return true; 192 } 193 194 // Neither symbol is week. They conflict. 195 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + 196 toString(Existing->getFile()) + "\n>>> defined in " + 197 toString(NewFile)); 198 return true; 199 } 200 201 Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, 202 InputFile *File, 203 InputFunction *Function) { 204 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" 205 << (Function ? toString(Function->Signature) : "none") 206 << "]\n"); 207 Symbol *S; 208 bool WasInserted; 209 std::tie(S, WasInserted) = insert(Name, File); 210 211 if (WasInserted || S->isLazy()) { 212 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 213 return S; 214 } 215 216 if (Function) 217 checkFunctionType(S, File, &Function->Signature); 218 219 if (shouldReplace(S, File, Flags)) { 220 // If the new defined function doesn't have signture (i.e. bitcode 221 // functions) but the old symbols does then preserve the old signature 222 const WasmSignature *OldSig = nullptr; 223 if (auto* F = dyn_cast<FunctionSymbol>(S)) 224 OldSig = F->FunctionType; 225 auto NewSym = replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 226 if (!NewSym->FunctionType) 227 NewSym->FunctionType = OldSig; 228 } 229 return S; 230 } 231 232 Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, 233 InputFile *File, InputSegment *Segment, 234 uint32_t Address, uint32_t Size) { 235 LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address 236 << "\n"); 237 Symbol *S; 238 bool WasInserted; 239 std::tie(S, WasInserted) = insert(Name, File); 240 241 if (WasInserted || S->isLazy()) { 242 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 243 return S; 244 } 245 246 checkDataType(S, File); 247 248 if (shouldReplace(S, File, Flags)) 249 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 250 return S; 251 } 252 253 Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, 254 InputFile *File, InputGlobal *Global) { 255 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); 256 257 Symbol *S; 258 bool WasInserted; 259 std::tie(S, WasInserted) = insert(Name, File); 260 261 if (WasInserted || S->isLazy()) { 262 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 263 return S; 264 } 265 266 checkGlobalType(S, File, &Global->getType()); 267 268 if (shouldReplace(S, File, Flags)) 269 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 270 return S; 271 } 272 273 Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags, 274 InputFile *File, 275 const WasmSignature *Sig) { 276 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << 277 " [" << (Sig ? toString(*Sig) : "none") << "]\n"); 278 279 Symbol *S; 280 bool WasInserted; 281 std::tie(S, WasInserted) = insert(Name, File); 282 283 if (WasInserted) 284 replaceSymbol<UndefinedFunction>(S, Name, Flags, File, Sig); 285 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 286 Lazy->fetch(); 287 else 288 checkFunctionType(S, File, Sig); 289 290 return S; 291 } 292 293 Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, 294 InputFile *File) { 295 LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); 296 297 Symbol *S; 298 bool WasInserted; 299 std::tie(S, WasInserted) = insert(Name, File); 300 301 if (WasInserted) 302 replaceSymbol<UndefinedData>(S, Name, Flags, File); 303 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 304 Lazy->fetch(); 305 else if (S->isDefined()) 306 checkDataType(S, File); 307 return S; 308 } 309 310 Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags, 311 InputFile *File, 312 const WasmGlobalType *Type) { 313 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); 314 315 Symbol *S; 316 bool WasInserted; 317 std::tie(S, WasInserted) = insert(Name, File); 318 319 if (WasInserted) 320 replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type); 321 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 322 Lazy->fetch(); 323 else if (S->isDefined()) 324 checkGlobalType(S, File, Type); 325 return S; 326 } 327 328 void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { 329 LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); 330 StringRef Name = Sym->getName(); 331 332 Symbol *S; 333 bool WasInserted; 334 std::tie(S, WasInserted) = insert(Name, nullptr); 335 336 if (WasInserted) { 337 replaceSymbol<LazySymbol>(S, Name, File, *Sym); 338 return; 339 } 340 341 // If there is an existing undefined symbol, load a new one from the archive. 342 if (S->isUndefined()) { 343 LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 344 File->addMember(Sym); 345 } 346 } 347 348 bool SymbolTable::addComdat(StringRef Name) { 349 return Comdats.insert(CachedHashStringRef(Name)).second; 350 } 351