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 << "\n"); 205 Symbol *S; 206 bool WasInserted; 207 std::tie(S, WasInserted) = insert(Name, File); 208 209 if (WasInserted || S->isLazy()) { 210 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 211 return S; 212 } 213 214 if (Function) 215 checkFunctionType(S, File, &Function->Signature); 216 217 if (shouldReplace(S, File, Flags)) 218 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); 219 return S; 220 } 221 222 Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, 223 InputFile *File, InputSegment *Segment, 224 uint32_t Address, uint32_t Size) { 225 LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address 226 << "\n"); 227 Symbol *S; 228 bool WasInserted; 229 std::tie(S, WasInserted) = insert(Name, File); 230 231 if (WasInserted || S->isLazy()) { 232 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 233 return S; 234 } 235 236 checkDataType(S, File); 237 238 if (shouldReplace(S, File, Flags)) 239 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 240 return S; 241 } 242 243 Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, 244 InputFile *File, InputGlobal *Global) { 245 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); 246 247 Symbol *S; 248 bool WasInserted; 249 std::tie(S, WasInserted) = insert(Name, File); 250 251 if (WasInserted || S->isLazy()) { 252 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 253 return S; 254 } 255 256 checkGlobalType(S, File, &Global->getType()); 257 258 if (shouldReplace(S, File, Flags)) 259 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 260 return S; 261 } 262 263 Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags, 264 InputFile *File, 265 const WasmSignature *Sig) { 266 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n"); 267 268 Symbol *S; 269 bool WasInserted; 270 std::tie(S, WasInserted) = insert(Name, File); 271 272 if (WasInserted) 273 replaceSymbol<UndefinedFunction>(S, Name, Flags, File, Sig); 274 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 275 Lazy->fetch(); 276 else 277 checkFunctionType(S, File, Sig); 278 279 return S; 280 } 281 282 Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, 283 InputFile *File) { 284 LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); 285 286 Symbol *S; 287 bool WasInserted; 288 std::tie(S, WasInserted) = insert(Name, File); 289 290 if (WasInserted) 291 replaceSymbol<UndefinedData>(S, Name, Flags, File); 292 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 293 Lazy->fetch(); 294 else if (S->isDefined()) 295 checkDataType(S, File); 296 return S; 297 } 298 299 Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags, 300 InputFile *File, 301 const WasmGlobalType *Type) { 302 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); 303 304 Symbol *S; 305 bool WasInserted; 306 std::tie(S, WasInserted) = insert(Name, File); 307 308 if (WasInserted) 309 replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type); 310 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 311 Lazy->fetch(); 312 else if (S->isDefined()) 313 checkGlobalType(S, File, Type); 314 return S; 315 } 316 317 void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { 318 LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); 319 StringRef Name = Sym->getName(); 320 321 Symbol *S; 322 bool WasInserted; 323 std::tie(S, WasInserted) = insert(Name, nullptr); 324 325 if (WasInserted) { 326 replaceSymbol<LazySymbol>(S, Name, File, *Sym); 327 return; 328 } 329 330 // If there is an existing undefined symbol, load a new one from the archive. 331 if (S->isUndefined()) { 332 LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 333 File->addMember(Sym); 334 } 335 } 336 337 bool SymbolTable::addComdat(StringRef Name) { 338 return Comdats.insert(CachedHashStringRef(Name)).second; 339 } 340