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