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 // Symbol table is a bag of all known symbols. We put all symbols of 11 // all input files to the symbol table. The symbol table is basically 12 // a hash table with the logic to resolve symbol name conflicts using 13 // the symbol types. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "SymbolTable.h" 18 #include "Config.h" 19 #include "Error.h" 20 #include "LinkerScript.h" 21 #include "Strings.h" 22 #include "Symbols.h" 23 #include "llvm/Bitcode/ReaderWriter.h" 24 #include "llvm/Support/StringSaver.h" 25 26 using namespace llvm; 27 using namespace llvm::object; 28 using namespace llvm::ELF; 29 30 using namespace lld; 31 using namespace lld::elf; 32 33 // All input object files must be for the same architecture 34 // (e.g. it does not make sense to link x86 object files with 35 // MIPS object files.) This function checks for that error. 36 template <class ELFT> static bool isCompatible(InputFile *F) { 37 if (!isa<ELFFileBase<ELFT>>(F) && !isa<BitcodeFile>(F)) 38 return true; 39 if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) 40 return true; 41 StringRef A = F->getName(); 42 StringRef B = Config->Emulation; 43 if (B.empty()) 44 B = Config->FirstElf->getName(); 45 error(A + " is incompatible with " + B); 46 return false; 47 } 48 49 // Add symbols in File to the symbol table. 50 template <class ELFT> 51 void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) { 52 InputFile *FileP = File.get(); 53 if (!isCompatible<ELFT>(FileP)) 54 return; 55 56 // .a file 57 if (auto *F = dyn_cast<ArchiveFile>(FileP)) { 58 ArchiveFiles.emplace_back(cast<ArchiveFile>(File.release())); 59 F->parse<ELFT>(); 60 return; 61 } 62 63 // Lazy object file 64 if (auto *F = dyn_cast<LazyObjectFile>(FileP)) { 65 LazyObjectFiles.emplace_back(cast<LazyObjectFile>(File.release())); 66 F->parse<ELFT>(); 67 return; 68 } 69 70 if (Config->Trace) 71 llvm::outs() << getFilename(FileP) << "\n"; 72 73 // .so file 74 if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) { 75 // DSOs are uniquified not by filename but by soname. 76 F->parseSoName(); 77 if (!SoNames.insert(F->getSoName()).second) 78 return; 79 80 SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release())); 81 F->parseRest(); 82 return; 83 } 84 85 // LLVM bitcode file 86 if (auto *F = dyn_cast<BitcodeFile>(FileP)) { 87 BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release())); 88 F->parse<ELFT>(ComdatGroups); 89 return; 90 } 91 92 // Regular object file 93 auto *F = cast<ObjectFile<ELFT>>(FileP); 94 ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release())); 95 F->parse(ComdatGroups); 96 } 97 98 // This function is where all the optimizations of link-time 99 // optimization happens. When LTO is in use, some input files are 100 // not in native object file format but in the LLVM bitcode format. 101 // This function compiles bitcode files into a few big native files 102 // using LLVM functions and replaces bitcode symbols with the results. 103 // Because all bitcode files that consist of a program are passed 104 // to the compiler at once, it can do whole-program optimization. 105 template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() { 106 if (BitcodeFiles.empty()) 107 return; 108 109 // Compile bitcode files. 110 Lto.reset(new BitcodeCompiler); 111 for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles) 112 Lto->add(*F); 113 std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile(); 114 115 // Replace bitcode symbols. 116 for (auto &IF : IFs) { 117 ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release()); 118 119 llvm::DenseSet<StringRef> DummyGroups; 120 Obj->parse(DummyGroups); 121 ObjectFiles.emplace_back(Obj); 122 } 123 } 124 125 template <class ELFT> 126 DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name, 127 uint8_t Visibility) { 128 return cast<DefinedRegular<ELFT>>( 129 addRegular(Name, STB_GLOBAL, Visibility)->body()); 130 } 131 132 // Add Name as an "ignored" symbol. An ignored symbol is a regular 133 // linker-synthesized defined symbol, but is only defined if needed. 134 template <class ELFT> 135 DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name, 136 uint8_t Visibility) { 137 if (!find(Name)) 138 return nullptr; 139 return addAbsolute(Name, Visibility); 140 } 141 142 // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. 143 // Used to implement --wrap. 144 template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) { 145 SymbolBody *B = find(Name); 146 if (!B) 147 return; 148 StringSaver Saver(Alloc); 149 Symbol *Sym = B->symbol(); 150 Symbol *Real = addUndefined(Saver.save("__real_" + Name)); 151 Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); 152 // We rename symbols by replacing the old symbol's SymbolBody with the new 153 // symbol's SymbolBody. This causes all SymbolBody pointers referring to the 154 // old symbol to instead refer to the new symbol. 155 memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body)); 156 memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body)); 157 } 158 159 static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { 160 if (VA == STV_DEFAULT) 161 return VB; 162 if (VB == STV_DEFAULT) 163 return VA; 164 return std::min(VA, VB); 165 } 166 167 // A symbol version may be included in a symbol name as a suffix after '@'. 168 // This function parses that part and returns a version ID number. 169 static uint16_t getVersionId(Symbol *Sym, StringRef Name) { 170 size_t VersionBegin = Name.find('@'); 171 if (VersionBegin == StringRef::npos) 172 return Config->VersionScriptGlobalByDefault ? VER_NDX_GLOBAL 173 : VER_NDX_LOCAL; 174 175 // If symbol name contains '@' or '@@' we can assign its version id right 176 // here. '@@' means the default version. It is usually the most recent one. 177 // VERSYM_HIDDEN flag should be set for all non-default versions. 178 StringRef Version = Name.drop_front(VersionBegin + 1); 179 bool Default = Version.startswith("@"); 180 if (Default) 181 Version = Version.drop_front(); 182 183 size_t I = 2; 184 for (elf::Version &V : Config->SymbolVersions) { 185 if (V.Name == Version) 186 return Default ? I : (I | VERSYM_HIDDEN); 187 ++I; 188 } 189 error("symbol " + Name + " has undefined version " + Version); 190 return 0; 191 } 192 193 // Find an existing symbol or create and insert a new one. 194 template <class ELFT> 195 std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) { 196 unsigned NumSyms = SymVector.size(); 197 auto P = Symtab.insert(std::make_pair(Name, NumSyms)); 198 Symbol *Sym; 199 if (P.second) { 200 Sym = new (Alloc) Symbol; 201 Sym->Binding = STB_WEAK; 202 Sym->Visibility = STV_DEFAULT; 203 Sym->IsUsedInRegularObj = false; 204 Sym->ExportDynamic = false; 205 Sym->VersionId = getVersionId(Sym, Name); 206 Sym->VersionedName = 207 Sym->VersionId != VER_NDX_LOCAL && Sym->VersionId != VER_NDX_GLOBAL; 208 SymVector.push_back(Sym); 209 } else { 210 Sym = SymVector[P.first->second]; 211 } 212 return {Sym, P.second}; 213 } 214 215 // Find an existing symbol or create and insert a new one, then apply the given 216 // attributes. 217 template <class ELFT> 218 std::pair<Symbol *, bool> 219 SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility, 220 bool CanOmitFromDynSym, bool IsUsedInRegularObj, 221 InputFile *File) { 222 Symbol *S; 223 bool WasInserted; 224 std::tie(S, WasInserted) = insert(Name); 225 226 // Merge in the new symbol's visibility. 227 S->Visibility = getMinVisibility(S->Visibility, Visibility); 228 if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) 229 S->ExportDynamic = true; 230 if (IsUsedInRegularObj) 231 S->IsUsedInRegularObj = true; 232 if (!WasInserted && S->body()->Type != SymbolBody::UnknownType && 233 ((Type == STT_TLS) != S->body()->isTls())) 234 error("TLS attribute mismatch for symbol: " + 235 conflictMsg(S->body(), File)); 236 237 return {S, WasInserted}; 238 } 239 240 // Construct a string in the form of "Sym in File1 and File2". 241 // Used to construct an error message. 242 template <typename ELFT> 243 std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing, 244 InputFile *NewFile) { 245 StringRef Sym = Existing->getName(); 246 return demangle(Sym) + " in " + getFilename(Existing->getSourceFile<ELFT>()) + 247 " and " + getFilename(NewFile); 248 } 249 250 template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) { 251 return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, 252 /*CanOmitFromDynSym*/ false, /*File*/ nullptr); 253 } 254 255 template <class ELFT> 256 Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding, 257 uint8_t StOther, uint8_t Type, 258 bool CanOmitFromDynSym, 259 InputFile *File) { 260 Symbol *S; 261 bool WasInserted; 262 std::tie(S, WasInserted) = 263 insert(Name, Type, StOther & 3, CanOmitFromDynSym, 264 /*IsUsedInRegularObj*/ !File || !isa<BitcodeFile>(File), File); 265 if (WasInserted) { 266 S->Binding = Binding; 267 replaceBody<Undefined>(S, Name, StOther, Type); 268 cast<Undefined>(S->body())->File = File; 269 return S; 270 } 271 if (Binding != STB_WEAK) { 272 if (S->body()->isShared() || S->body()->isLazy()) 273 S->Binding = Binding; 274 if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body())) 275 SS->File->IsUsed = true; 276 } 277 if (auto *L = dyn_cast<Lazy>(S->body())) { 278 // An undefined weak will not fetch archive members, but we have to remember 279 // its type. See also comment in addLazyArchive. 280 if (S->isWeak()) 281 L->Type = Type; 282 else if (auto F = L->getFile()) 283 addFile(std::move(F)); 284 } 285 return S; 286 } 287 288 // We have a new defined symbol with the specified binding. Return 1 if the new 289 // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are 290 // strong defined symbols. 291 static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) { 292 if (WasInserted) 293 return 1; 294 SymbolBody *Body = S->body(); 295 if (Body->isLazy() || Body->isUndefined() || Body->isShared()) 296 return 1; 297 if (Binding == STB_WEAK) 298 return -1; 299 if (S->isWeak()) 300 return 1; 301 return 0; 302 } 303 304 // We have a new non-common defined symbol with the specified binding. Return 1 305 // if the new symbol should win, -1 if the new symbol should lose, or 0 if there 306 // is a conflict. If the new symbol wins, also update the binding. 307 static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding) { 308 if (int Cmp = compareDefined(S, WasInserted, Binding)) { 309 if (Cmp > 0) 310 S->Binding = Binding; 311 return Cmp; 312 } 313 if (isa<DefinedCommon>(S->body())) { 314 // Non-common symbols take precedence over common symbols. 315 if (Config->WarnCommon) 316 warning("common " + S->body()->getName() + " is overridden"); 317 return 1; 318 } 319 return 0; 320 } 321 322 template <class ELFT> 323 Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size, 324 uint64_t Alignment, uint8_t Binding, 325 uint8_t StOther, uint8_t Type, 326 InputFile *File) { 327 Symbol *S; 328 bool WasInserted; 329 std::tie(S, WasInserted) = 330 insert(N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, 331 /*IsUsedInRegularObj*/ true, File); 332 int Cmp = compareDefined(S, WasInserted, Binding); 333 if (Cmp > 0) { 334 S->Binding = Binding; 335 replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type); 336 } else if (Cmp == 0) { 337 auto *C = dyn_cast<DefinedCommon>(S->body()); 338 if (!C) { 339 // Non-common symbols take precedence over common symbols. 340 if (Config->WarnCommon) 341 warning("common " + S->body()->getName() + " is overridden"); 342 return S; 343 } 344 345 if (Config->WarnCommon) 346 warning("multiple common of " + S->body()->getName()); 347 348 C->Size = std::max(C->Size, Size); 349 C->Alignment = std::max(C->Alignment, Alignment); 350 } 351 return S; 352 } 353 354 template <class ELFT> 355 void SymbolTable<ELFT>::reportDuplicate(SymbolBody *Existing, 356 InputFile *NewFile) { 357 std::string Msg = "duplicate symbol: " + conflictMsg(Existing, NewFile); 358 if (Config->AllowMultipleDefinition) 359 warning(Msg); 360 else 361 error(Msg); 362 } 363 364 template <typename ELFT> 365 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym, 366 InputSectionBase<ELFT> *Section) { 367 Symbol *S; 368 bool WasInserted; 369 std::tie(S, WasInserted) = 370 insert(Name, Sym.getType(), Sym.getVisibility(), 371 /*CanOmitFromDynSym*/ false, /*IsUsedInRegularObj*/ true, 372 Section ? Section->getFile() : nullptr); 373 int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding()); 374 if (Cmp > 0) 375 replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section); 376 else if (Cmp == 0) 377 reportDuplicate(S->body(), Section->getFile()); 378 return S; 379 } 380 381 template <typename ELFT> 382 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding, 383 uint8_t StOther) { 384 Symbol *S; 385 bool WasInserted; 386 std::tie(S, WasInserted) = 387 insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false, 388 /*IsUsedInRegularObj*/ true, nullptr); 389 int Cmp = compareDefinedNonCommon(S, WasInserted, Binding); 390 if (Cmp > 0) 391 replaceBody<DefinedRegular<ELFT>>(S, Name, StOther); 392 else if (Cmp == 0) 393 reportDuplicate(S->body(), nullptr); 394 return S; 395 } 396 397 template <typename ELFT> 398 Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N, 399 OutputSectionBase<ELFT> *Section, 400 uintX_t Value) { 401 Symbol *S; 402 bool WasInserted; 403 std::tie(S, WasInserted) = 404 insert(N, STT_NOTYPE, STV_HIDDEN, /*CanOmitFromDynSym*/ false, 405 /*IsUsedInRegularObj*/ true, nullptr); 406 int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL); 407 if (Cmp > 0) 408 replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section); 409 else if (Cmp == 0) 410 reportDuplicate(S->body(), nullptr); 411 return S; 412 } 413 414 template <typename ELFT> 415 void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name, 416 const Elf_Sym &Sym, 417 const typename ELFT::Verdef *Verdef) { 418 // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT 419 // as the visibility, which will leave the visibility in the symbol table 420 // unchanged. 421 Symbol *S; 422 bool WasInserted; 423 std::tie(S, WasInserted) = 424 insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, 425 /*IsUsedInRegularObj*/ false, F); 426 // Make sure we preempt DSO symbols with default visibility. 427 if (Sym.getVisibility() == STV_DEFAULT) 428 S->ExportDynamic = true; 429 if (WasInserted || isa<Undefined>(S->body())) { 430 replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef); 431 if (!S->isWeak()) 432 F->IsUsed = true; 433 } 434 } 435 436 template <class ELFT> 437 Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, bool IsWeak, 438 uint8_t StOther, uint8_t Type, 439 bool CanOmitFromDynSym, BitcodeFile *F) { 440 Symbol *S; 441 bool WasInserted; 442 std::tie(S, WasInserted) = insert(Name, Type, StOther & 3, CanOmitFromDynSym, 443 /*IsUsedInRegularObj*/ false, F); 444 int Cmp = 445 compareDefinedNonCommon(S, WasInserted, IsWeak ? STB_WEAK : STB_GLOBAL); 446 if (Cmp > 0) 447 replaceBody<DefinedBitcode>(S, Name, StOther, Type, F); 448 else if (Cmp == 0) 449 reportDuplicate(S->body(), F); 450 return S; 451 } 452 453 template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) { 454 auto It = Symtab.find(Name); 455 if (It == Symtab.end()) 456 return nullptr; 457 return SymVector[It->second]->body(); 458 } 459 460 // Returns a list of defined symbols that match with a given glob pattern. 461 template <class ELFT> 462 std::vector<SymbolBody *> SymbolTable<ELFT>::findAll(StringRef Pattern) { 463 // Fast-path. Fallback to find() if Pattern doesn't contain any wildcard 464 // characters. 465 if (Pattern.find_first_of("?*") == StringRef::npos) { 466 if (SymbolBody *B = find(Pattern)) 467 if (!B->isUndefined()) 468 return {B}; 469 return {}; 470 } 471 472 std::vector<SymbolBody *> Res; 473 for (auto &It : Symtab) { 474 StringRef Name = It.first.Val; 475 SymbolBody *B = SymVector[It.second]->body(); 476 if (!B->isUndefined() && globMatch(Pattern, Name)) 477 Res.push_back(B); 478 } 479 return Res; 480 } 481 482 template <class ELFT> 483 void SymbolTable<ELFT>::addLazyArchive( 484 ArchiveFile *F, const llvm::object::Archive::Symbol Sym) { 485 Symbol *S; 486 bool WasInserted; 487 std::tie(S, WasInserted) = insert(Sym.getName()); 488 if (WasInserted) { 489 replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType); 490 return; 491 } 492 if (!S->body()->isUndefined()) 493 return; 494 495 // Weak undefined symbols should not fetch members from archives. If we were 496 // to keep old symbol we would not know that an archive member was available 497 // if a strong undefined symbol shows up afterwards in the link. If a strong 498 // undefined symbol never shows up, this lazy symbol will get to the end of 499 // the link and must be treated as the weak undefined one. We already marked 500 // this symbol as used when we added it to the symbol table, but we also need 501 // to preserve its type. FIXME: Move the Type field to Symbol. 502 if (S->isWeak()) { 503 replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type); 504 return; 505 } 506 MemoryBufferRef MBRef = F->getMember(&Sym); 507 if (!MBRef.getBuffer().empty()) 508 addFile(createObjectFile(MBRef, F->getName())); 509 } 510 511 template <class ELFT> 512 void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) { 513 Symbol *S; 514 bool WasInserted; 515 std::tie(S, WasInserted) = insert(Name); 516 if (WasInserted) { 517 replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType); 518 return; 519 } 520 if (!S->body()->isUndefined()) 521 return; 522 523 // See comment for addLazyArchive above. 524 if (S->isWeak()) { 525 replaceBody<LazyObject>(S, Name, Obj, S->body()->Type); 526 } else { 527 MemoryBufferRef MBRef = Obj.getBuffer(); 528 if (!MBRef.getBuffer().empty()) 529 addFile(createObjectFile(MBRef)); 530 } 531 } 532 533 // Process undefined (-u) flags by loading lazy symbols named by those flags. 534 template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() { 535 for (StringRef S : Config->Undefined) 536 if (auto *L = dyn_cast_or_null<Lazy>(find(S))) 537 if (std::unique_ptr<InputFile> File = L->getFile()) 538 addFile(std::move(File)); 539 } 540 541 // This function takes care of the case in which shared libraries depend on 542 // the user program (not the other way, which is usual). Shared libraries 543 // may have undefined symbols, expecting that the user program provides 544 // the definitions for them. An example is BSD's __progname symbol. 545 // We need to put such symbols to the main program's .dynsym so that 546 // shared libraries can find them. 547 // Except this, we ignore undefined symbols in DSOs. 548 template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { 549 for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles) 550 for (StringRef U : File->getUndefinedSymbols()) 551 if (SymbolBody *Sym = find(U)) 552 if (Sym->isDefined()) 553 Sym->symbol()->ExportDynamic = true; 554 } 555 556 // This function process the dynamic list option by marking all the symbols 557 // to be exported in the dynamic table. 558 template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() { 559 for (StringRef S : Config->DynamicList) 560 if (SymbolBody *B = find(S)) 561 B->symbol()->ExportDynamic = true; 562 } 563 564 // This function processes the --version-script option by marking all global 565 // symbols with the VersionScriptGlobal flag, which acts as a filter on the 566 // dynamic symbol table. 567 template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { 568 // If version script does not contain versions declarations, 569 // we just should mark global symbols. 570 if (!Config->VersionScriptGlobals.empty()) { 571 for (StringRef S : Config->VersionScriptGlobals) 572 if (SymbolBody *B = find(S)) 573 B->symbol()->VersionId = VER_NDX_GLOBAL; 574 return; 575 } 576 577 // If we have symbols version declarations, we should 578 // assign version references for each symbol. 579 size_t I = 2; 580 for (Version &V : Config->SymbolVersions) { 581 for (StringRef Name : V.Globals) { 582 std::vector<SymbolBody *> Syms = findAll(Name); 583 if (Syms.empty()) { 584 if (Config->NoUndefinedVersion) 585 error("version script assignment of " + V.Name + " to symbol " + 586 Name + " failed: symbol not defined"); 587 continue; 588 } 589 590 for (SymbolBody *B : Syms) { 591 if (B->symbol()->VersionId != VER_NDX_GLOBAL && 592 B->symbol()->VersionId != VER_NDX_LOCAL) 593 warning("duplicate symbol " + Name + " in version script"); 594 B->symbol()->VersionId = I; 595 } 596 } 597 ++I; 598 } 599 } 600 601 // Print the module names which define the notified 602 // symbols provided through -y or --trace-symbol option. 603 template <class ELFT> void SymbolTable<ELFT>::traceDefined() { 604 for (const auto &Symbol : Config->TraceSymbol) 605 if (SymbolBody *B = find(Symbol.getKey())) 606 if (B->isDefined() || B->isCommon()) 607 if (InputFile *File = B->getSourceFile<ELFT>()) 608 outs() << getFilename(File) << ": definition of " 609 << B->getName() << "\n"; 610 } 611 612 template class elf::SymbolTable<ELF32LE>; 613 template class elf::SymbolTable<ELF32BE>; 614 template class elf::SymbolTable<ELF64LE>; 615 template class elf::SymbolTable<ELF64BE>; 616