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 SetVector<Symbol *> Undefs; 64 for (Symbol *Sym : SymVector) { 65 if (!Sym->isUndefined() || Sym->isWeak()) 66 continue; 67 if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0) 68 continue; 69 if (!Sym->IsUsedInRegularObj) 70 continue; 71 Undefs.insert(Sym); 72 } 73 74 if (Undefs.empty()) 75 return; 76 77 for (ObjFile *File : ObjectFiles) 78 for (Symbol *Sym : File->getSymbols()) 79 if (Undefs.count(Sym)) 80 error(toString(File) + ": undefined symbol: " + toString(*Sym)); 81 82 for (Symbol *Sym : Undefs) 83 if (!Sym->getFile()) 84 error("undefined symbol: " + toString(*Sym)); 85 } 86 87 Symbol *SymbolTable::find(StringRef Name) { 88 return SymMap.lookup(CachedHashStringRef(Name)); 89 } 90 91 std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { 92 Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; 93 if (Sym) 94 return {Sym, false}; 95 Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 96 Sym->IsUsedInRegularObj = false; 97 SymVector.emplace_back(Sym); 98 return {Sym, true}; 99 } 100 101 static void reportTypeError(const Symbol *Existing, const InputFile *File, 102 llvm::wasm::WasmSymbolType Type) { 103 error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + 104 toString(Existing->getWasmType()) + " in " + 105 toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + 106 " in " + toString(File)); 107 } 108 109 static void checkFunctionType(Symbol *Existing, const InputFile *File, 110 const WasmSignature *NewSig) { 111 auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing); 112 if (!ExistingFunction) { 113 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION); 114 return; 115 } 116 117 118 const WasmSignature *OldSig = ExistingFunction->getFunctionType(); 119 if (OldSig && NewSig && *NewSig != *OldSig) { 120 // Don't generate more than one warning per symbol. 121 if (Existing->SignatureMismatch) 122 return; 123 Existing->SignatureMismatch = true; 124 125 std::string msg = ("function signature mismatch: " + Existing->getName() + 126 "\n>>> defined as " + toString(*OldSig) + " in " + 127 toString(Existing->getFile()) + "\n>>> defined as " + 128 toString(*NewSig) + " in " + toString(File)) 129 .str(); 130 // A function signature mismatch is only really problem if the mismatched 131 // symbol is included in the final output, and gc-sections can remove the 132 // offending uses. Therefore we delay reporting this as an error when 133 // section GC is enabled. 134 if (Config->GcSections) 135 warn(msg); 136 else 137 error(msg); 138 } 139 } 140 141 // Check the type of new symbol matches that of the symbol is replacing. 142 // For functions this can also involve verifying that the signatures match. 143 static void checkGlobalType(const Symbol *Existing, const InputFile *File, 144 const WasmGlobalType *NewType) { 145 if (!isa<GlobalSymbol>(Existing)) { 146 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); 147 return; 148 } 149 150 const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType(); 151 if (*NewType != *OldType) { 152 error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + 153 toString(*OldType) + " in " + toString(Existing->getFile()) + 154 "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 155 } 156 } 157 158 static void checkDataType(const Symbol *Existing, const InputFile *File) { 159 if (!isa<DataSymbol>(Existing)) 160 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); 161 } 162 163 DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, 164 uint32_t Flags, 165 InputFunction *Function) { 166 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); 167 assert(!find(Name)); 168 SyntheticFunctions.emplace_back(Function); 169 return replaceSymbol<DefinedFunction>(insert(Name).first, Name, Flags, 170 nullptr, Function); 171 } 172 173 DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, 174 uint32_t Flags) { 175 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); 176 assert(!find(Name)); 177 return replaceSymbol<DefinedData>(insert(Name).first, Name, Flags); 178 } 179 180 DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, 181 InputGlobal *Global) { 182 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global 183 << "\n"); 184 assert(!find(Name)); 185 SyntheticGlobals.emplace_back(Global); 186 return replaceSymbol<DefinedGlobal>(insert(Name).first, Name, Flags, nullptr, 187 Global); 188 } 189 190 static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, 191 uint32_t NewFlags) { 192 // If existing symbol is undefined, replace it. 193 if (!Existing->isDefined()) { 194 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 195 << Existing->getName() << "\n"); 196 return true; 197 } 198 199 // Now we have two defined symbols. If the new one is weak, we can ignore it. 200 if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 201 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 202 return false; 203 } 204 205 // If the existing symbol is weak, we should replace it. 206 if (Existing->isWeak()) { 207 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 208 return true; 209 } 210 211 // Neither symbol is week. They conflict. 212 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + 213 toString(Existing->getFile()) + "\n>>> defined in " + 214 toString(NewFile)); 215 return true; 216 } 217 218 Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, 219 InputFile *File, 220 InputFunction *Function) { 221 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n"); 222 Symbol *S; 223 bool WasInserted; 224 std::tie(S, WasInserted) = insert(Name); 225 226 if (!File || File->kind() == InputFile::ObjectKind) 227 S->IsUsedInRegularObj = true; 228 229 if (WasInserted || S->isLazy()) { 230 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 231 return S; 232 } 233 234 if (Function) 235 checkFunctionType(S, File, &Function->Signature); 236 237 if (shouldReplace(S, File, Flags)) 238 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 239 return S; 240 } 241 242 Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, 243 InputFile *File, InputSegment *Segment, 244 uint32_t Address, uint32_t Size) { 245 LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address 246 << "\n"); 247 Symbol *S; 248 bool WasInserted; 249 std::tie(S, WasInserted) = insert(Name); 250 251 if (!File || File->kind() == InputFile::ObjectKind) 252 S->IsUsedInRegularObj = true; 253 254 if (WasInserted || S->isLazy()) { 255 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 256 return S; 257 } 258 259 checkDataType(S, File); 260 261 if (shouldReplace(S, File, Flags)) 262 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 263 return S; 264 } 265 266 Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, 267 InputFile *File, InputGlobal *Global) { 268 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); 269 Symbol *S; 270 bool WasInserted; 271 std::tie(S, WasInserted) = insert(Name); 272 273 if (!File || File->kind() == InputFile::ObjectKind) 274 S->IsUsedInRegularObj = true; 275 276 if (WasInserted || S->isLazy()) { 277 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 278 return S; 279 } 280 281 checkGlobalType(S, File, &Global->getType()); 282 283 if (shouldReplace(S, File, Flags)) 284 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 285 return S; 286 } 287 288 Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags, 289 InputFile *File, 290 const WasmSignature *Sig) { 291 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n"); 292 293 Symbol *S; 294 bool WasInserted; 295 std::tie(S, WasInserted) = insert(Name); 296 297 if (!File || File->kind() == InputFile::ObjectKind) 298 S->IsUsedInRegularObj = true; 299 300 if (WasInserted) 301 replaceSymbol<UndefinedFunction>(S, Name, Flags, File, Sig); 302 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 303 Lazy->fetch(); 304 else if (S->isDefined()) 305 checkFunctionType(S, File, Sig); 306 return S; 307 } 308 309 Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, 310 InputFile *File) { 311 LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); 312 313 Symbol *S; 314 bool WasInserted; 315 std::tie(S, WasInserted) = insert(Name); 316 317 if (WasInserted) 318 replaceSymbol<UndefinedData>(S, Name, Flags, File); 319 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 320 Lazy->fetch(); 321 else if (S->isDefined()) 322 checkDataType(S, File); 323 return S; 324 } 325 326 Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags, 327 InputFile *File, 328 const WasmGlobalType *Type) { 329 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); 330 331 Symbol *S; 332 bool WasInserted; 333 std::tie(S, WasInserted) = insert(Name); 334 335 if (!File || File->kind() == InputFile::ObjectKind) 336 S->IsUsedInRegularObj = true; 337 338 if (WasInserted) 339 replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type); 340 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 341 Lazy->fetch(); 342 else if (S->isDefined()) 343 checkGlobalType(S, File, Type); 344 return S; 345 } 346 347 void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { 348 LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); 349 StringRef Name = Sym->getName(); 350 351 Symbol *S; 352 bool WasInserted; 353 std::tie(S, WasInserted) = insert(Name); 354 355 if (WasInserted) { 356 replaceSymbol<LazySymbol>(S, Name, File, *Sym); 357 return; 358 } 359 360 // If there is an existing undefined symbol, load a new one from the archive. 361 if (S->isUndefined()) { 362 LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 363 File->addMember(Sym); 364 } 365 } 366 367 bool SymbolTable::addComdat(StringRef Name) { 368 return Comdats.insert(CachedHashStringRef(Name)).second; 369 } 370