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