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 "SymbolListFile.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> void SymbolTable<ELFT>::addFile(InputFile *File) { 51 if (!isCompatible<ELFT>(File)) 52 return; 53 54 // Binary file 55 if (auto *F = dyn_cast<BinaryFile>(File)) { 56 addFile(F->createELF<ELFT>()); 57 return; 58 } 59 60 // .a file 61 if (auto *F = dyn_cast<ArchiveFile>(File)) { 62 F->parse<ELFT>(); 63 return; 64 } 65 66 // Lazy object file 67 if (auto *F = dyn_cast<LazyObjectFile>(File)) { 68 F->parse<ELFT>(); 69 return; 70 } 71 72 if (Config->Trace) 73 outs() << getFilename(File) << "\n"; 74 75 // .so file 76 if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { 77 // DSOs are uniquified not by filename but by soname. 78 F->parseSoName(); 79 if (!SoNames.insert(F->getSoName()).second) 80 return; 81 SharedFiles.push_back(F); 82 F->parseRest(); 83 return; 84 } 85 86 // LLVM bitcode file 87 if (auto *F = dyn_cast<BitcodeFile>(File)) { 88 BitcodeFiles.push_back(F); 89 F->parse<ELFT>(ComdatGroups); 90 return; 91 } 92 93 // Regular object file 94 auto *F = cast<ObjectFile<ELFT>>(File); 95 ObjectFiles.push_back(F); 96 F->parse(ComdatGroups); 97 } 98 99 // This function is where all the optimizations of link-time 100 // optimization happens. When LTO is in use, some input files are 101 // not in native object file format but in the LLVM bitcode format. 102 // This function compiles bitcode files into a few big native files 103 // using LLVM functions and replaces bitcode symbols with the results. 104 // Because all bitcode files that consist of a program are passed 105 // to the compiler at once, it can do whole-program optimization. 106 template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() { 107 if (BitcodeFiles.empty()) 108 return; 109 110 // Compile bitcode files and replace bitcode symbols. 111 Lto.reset(new BitcodeCompiler); 112 for (BitcodeFile *F : BitcodeFiles) 113 Lto->add(*F); 114 115 for (InputFile *File : Lto->compile()) { 116 ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File); 117 DenseSet<StringRef> DummyGroups; 118 Obj->parse(DummyGroups); 119 ObjectFiles.push_back(Obj); 120 } 121 } 122 123 template <class ELFT> 124 DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name, 125 uint8_t Visibility) { 126 return cast<DefinedRegular<ELFT>>( 127 addRegular(Name, STB_GLOBAL, Visibility)->body()); 128 } 129 130 // Add Name as an "ignored" symbol. An ignored symbol is a regular 131 // linker-synthesized defined symbol, but is only defined if needed. 132 template <class ELFT> 133 DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name, 134 uint8_t Visibility) { 135 if (!find(Name)) 136 return nullptr; 137 return addAbsolute(Name, Visibility); 138 } 139 140 // Set a flag for --trace-symbol so that we can print out a log message 141 // if a new symbol with the same name is inserted into the symbol table. 142 template <class ELFT> void SymbolTable<ELFT>::trace(StringRef Name) { 143 Symtab.insert({Name, {-1, true}}); 144 } 145 146 // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. 147 // Used to implement --wrap. 148 template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) { 149 SymbolBody *B = find(Name); 150 if (!B) 151 return; 152 StringSaver Saver(Alloc); 153 Symbol *Sym = B->symbol(); 154 Symbol *Real = addUndefined(Saver.save("__real_" + Name)); 155 Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); 156 // We rename symbols by replacing the old symbol's SymbolBody with the new 157 // symbol's SymbolBody. This causes all SymbolBody pointers referring to the 158 // old symbol to instead refer to the new symbol. 159 memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body)); 160 memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body)); 161 } 162 163 static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { 164 if (VA == STV_DEFAULT) 165 return VB; 166 if (VB == STV_DEFAULT) 167 return VA; 168 return std::min(VA, VB); 169 } 170 171 // Parses a symbol in the form of <name>@<version> or <name>@@<version>. 172 static std::pair<StringRef, uint16_t> getSymbolVersion(StringRef S) { 173 if (Config->VersionDefinitions.empty()) 174 return {S, Config->DefaultSymbolVersion}; 175 176 size_t Pos = S.find('@'); 177 if (Pos == 0 || Pos == StringRef::npos) 178 return {S, Config->DefaultSymbolVersion}; 179 180 StringRef Name = S.substr(0, Pos); 181 StringRef Verstr = S.substr(Pos + 1); 182 if (Verstr.empty()) 183 return {S, Config->DefaultSymbolVersion}; 184 185 // '@@' in a symbol name means the default version. 186 // It is usually the most recent one. 187 bool IsDefault = (Verstr[0] == '@'); 188 if (IsDefault) 189 Verstr = Verstr.substr(1); 190 191 for (VersionDefinition &V : Config->VersionDefinitions) { 192 if (V.Name == Verstr) 193 return {Name, IsDefault ? V.Id : (V.Id | VERSYM_HIDDEN)}; 194 } 195 196 // It is an error if the specified version was not defined. 197 error("symbol " + S + " has undefined version " + Verstr); 198 return {S, Config->DefaultSymbolVersion}; 199 } 200 201 // Find an existing symbol or create and insert a new one. 202 template <class ELFT> 203 std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef &Name) { 204 auto P = Symtab.insert({Name, SymIndex((int)SymVector.size(), false)}); 205 SymIndex &V = P.first->second; 206 bool IsNew = P.second; 207 208 if (V.Idx == -1) { 209 IsNew = true; 210 V = SymIndex((int)SymVector.size(), true); 211 } 212 213 Symbol *Sym; 214 if (IsNew) { 215 Sym = new (Alloc) Symbol; 216 Sym->Binding = STB_WEAK; 217 Sym->Visibility = STV_DEFAULT; 218 Sym->IsUsedInRegularObj = false; 219 Sym->HasUnnamedAddr = true; 220 Sym->ExportDynamic = false; 221 Sym->Traced = V.Traced; 222 std::tie(Name, Sym->VersionId) = getSymbolVersion(Name); 223 SymVector.push_back(Sym); 224 } else { 225 Sym = SymVector[V.Idx]; 226 } 227 return {Sym, IsNew}; 228 } 229 230 // Find an existing symbol or create and insert a new one, then apply the given 231 // attributes. 232 template <class ELFT> 233 std::pair<Symbol *, bool> 234 SymbolTable<ELFT>::insert(StringRef &Name, uint8_t Type, uint8_t Visibility, 235 bool CanOmitFromDynSym, bool HasUnnamedAddr, 236 InputFile *File) { 237 bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind; 238 Symbol *S; 239 bool WasInserted; 240 std::tie(S, WasInserted) = insert(Name); 241 242 // Merge in the new unnamed_addr attribute. 243 S->HasUnnamedAddr &= HasUnnamedAddr; 244 // Merge in the new symbol's visibility. 245 S->Visibility = getMinVisibility(S->Visibility, Visibility); 246 if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) 247 S->ExportDynamic = true; 248 if (IsUsedInRegularObj) 249 S->IsUsedInRegularObj = true; 250 if (!WasInserted && S->body()->Type != SymbolBody::UnknownType && 251 ((Type == STT_TLS) != S->body()->isTls())) 252 error("TLS attribute mismatch for symbol: " + 253 conflictMsg(S->body(), File)); 254 255 return {S, WasInserted}; 256 } 257 258 // Construct a string in the form of "Sym in File1 and File2". 259 // Used to construct an error message. 260 template <typename ELFT> 261 std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing, 262 InputFile *NewFile) { 263 std::string Sym = Existing->getName(); 264 if (Config->Demangle) 265 Sym = demangle(Sym); 266 return Sym + " in " + getFilename(Existing->File) + " and " + 267 getFilename(NewFile); 268 } 269 270 template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) { 271 return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, 272 /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false, 273 /*File*/ nullptr); 274 } 275 276 template <class ELFT> 277 Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding, 278 uint8_t StOther, uint8_t Type, 279 bool CanOmitFromDynSym, 280 bool HasUnnamedAddr, InputFile *File) { 281 Symbol *S; 282 bool WasInserted; 283 std::tie(S, WasInserted) = 284 insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, File); 285 if (WasInserted) { 286 S->Binding = Binding; 287 replaceBody<Undefined>(S, Name, StOther, Type, File); 288 return S; 289 } 290 if (Binding != STB_WEAK) { 291 if (S->body()->isShared() || S->body()->isLazy()) 292 S->Binding = Binding; 293 if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body())) 294 SS->file()->IsUsed = true; 295 } 296 if (auto *L = dyn_cast<Lazy>(S->body())) { 297 // An undefined weak will not fetch archive members, but we have to remember 298 // its type. See also comment in addLazyArchive. 299 if (S->isWeak()) 300 L->Type = Type; 301 else if (InputFile *F = L->fetch()) 302 addFile(F); 303 } 304 return S; 305 } 306 307 // We have a new defined symbol with the specified binding. Return 1 if the new 308 // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are 309 // strong defined symbols. 310 static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) { 311 if (WasInserted) 312 return 1; 313 SymbolBody *Body = S->body(); 314 if (Body->isLazy() || Body->isUndefined() || Body->isShared()) 315 return 1; 316 if (Binding == STB_WEAK) 317 return -1; 318 if (S->isWeak()) 319 return 1; 320 return 0; 321 } 322 323 // We have a new non-common defined symbol with the specified binding. Return 1 324 // if the new symbol should win, -1 if the new symbol should lose, or 0 if there 325 // is a conflict. If the new symbol wins, also update the binding. 326 static int compareDefinedNonCommon(Symbol *S, bool WasInserted, 327 uint8_t Binding) { 328 if (int Cmp = compareDefined(S, WasInserted, Binding)) { 329 if (Cmp > 0) 330 S->Binding = Binding; 331 return Cmp; 332 } 333 if (isa<DefinedCommon>(S->body())) { 334 // Non-common symbols take precedence over common symbols. 335 if (Config->WarnCommon) 336 warning("common " + S->body()->getName() + " is overridden"); 337 return 1; 338 } 339 return 0; 340 } 341 342 template <class ELFT> 343 Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size, 344 uint64_t Alignment, uint8_t Binding, 345 uint8_t StOther, uint8_t Type, 346 bool HasUnnamedAddr, InputFile *File) { 347 Symbol *S; 348 bool WasInserted; 349 std::tie(S, WasInserted) = insert( 350 N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, HasUnnamedAddr, File); 351 int Cmp = compareDefined(S, WasInserted, Binding); 352 if (Cmp > 0) { 353 S->Binding = Binding; 354 replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File); 355 } else if (Cmp == 0) { 356 auto *C = dyn_cast<DefinedCommon>(S->body()); 357 if (!C) { 358 // Non-common symbols take precedence over common symbols. 359 if (Config->WarnCommon) 360 warning("common " + S->body()->getName() + " is overridden"); 361 return S; 362 } 363 364 if (Config->WarnCommon) 365 warning("multiple common of " + S->body()->getName()); 366 367 Alignment = C->Alignment = std::max(C->Alignment, Alignment); 368 if (Size > C->Size) 369 replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File); 370 } 371 return S; 372 } 373 374 template <class ELFT> 375 void SymbolTable<ELFT>::reportDuplicate(SymbolBody *Existing, 376 InputFile *NewFile) { 377 std::string Msg = "duplicate symbol: " + conflictMsg(Existing, NewFile); 378 if (Config->AllowMultipleDefinition) 379 warning(Msg); 380 else 381 error(Msg); 382 } 383 384 template <typename ELFT> 385 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym, 386 InputSectionBase<ELFT> *Section) { 387 Symbol *S; 388 bool WasInserted; 389 std::tie(S, WasInserted) = 390 insert(Name, Sym.getType(), Sym.getVisibility(), 391 /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false, 392 Section ? Section->getFile() : nullptr); 393 int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding()); 394 if (Cmp > 0) 395 replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section); 396 else if (Cmp == 0) 397 reportDuplicate(S->body(), Section->getFile()); 398 return S; 399 } 400 401 template <typename ELFT> 402 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding, 403 uint8_t StOther) { 404 Symbol *S; 405 bool WasInserted; 406 std::tie(S, WasInserted) = 407 insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false, 408 /*HasUnnamedAddr*/ false, nullptr); 409 int Cmp = compareDefinedNonCommon(S, WasInserted, Binding); 410 if (Cmp > 0) 411 replaceBody<DefinedRegular<ELFT>>(S, Name, StOther); 412 else if (Cmp == 0) 413 reportDuplicate(S->body(), nullptr); 414 return S; 415 } 416 417 template <typename ELFT> 418 Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N, 419 OutputSectionBase<ELFT> *Section, 420 uintX_t Value, uint8_t StOther) { 421 Symbol *S; 422 bool WasInserted; 423 std::tie(S, WasInserted) = insert(N, STT_NOTYPE, /*Visibility*/ StOther & 0x3, 424 /*CanOmitFromDynSym*/ false, 425 /*HasUnnamedAddr*/ false, nullptr); 426 int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL); 427 if (Cmp > 0) 428 replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section); 429 else if (Cmp == 0) 430 reportDuplicate(S->body(), nullptr); 431 return S; 432 } 433 434 template <typename ELFT> 435 void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name, 436 const Elf_Sym &Sym, 437 const typename ELFT::Verdef *Verdef) { 438 // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT 439 // as the visibility, which will leave the visibility in the symbol table 440 // unchanged. 441 Symbol *S; 442 bool WasInserted; 443 std::tie(S, WasInserted) = 444 insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, 445 /*HasUnnamedAddr*/ false, F); 446 // Make sure we preempt DSO symbols with default visibility. 447 if (Sym.getVisibility() == STV_DEFAULT) 448 S->ExportDynamic = true; 449 if (WasInserted || isa<Undefined>(S->body())) { 450 replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef); 451 if (!S->isWeak()) 452 F->IsUsed = true; 453 } 454 } 455 456 template <class ELFT> 457 Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding, 458 uint8_t StOther, uint8_t Type, 459 bool CanOmitFromDynSym, 460 bool HasUnnamedAddr, BitcodeFile *F) { 461 Symbol *S; 462 bool WasInserted; 463 std::tie(S, WasInserted) = 464 insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, F); 465 int Cmp = compareDefinedNonCommon(S, WasInserted, Binding); 466 if (Cmp > 0) 467 replaceBody<DefinedRegular<ELFT>>(S, Name, StOther, Type, F); 468 else if (Cmp == 0) 469 reportDuplicate(S->body(), F); 470 return S; 471 } 472 473 template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) { 474 auto It = Symtab.find(Name); 475 if (It == Symtab.end()) 476 return nullptr; 477 SymIndex V = It->second; 478 if (V.Idx == -1) 479 return nullptr; 480 return SymVector[V.Idx]->body(); 481 } 482 483 // Returns a list of defined symbols that match with a given regex. 484 template <class ELFT> 485 std::vector<SymbolBody *> SymbolTable<ELFT>::findAll(const Regex &Re) { 486 std::vector<SymbolBody *> Res; 487 for (Symbol *Sym : SymVector) { 488 SymbolBody *B = Sym->body(); 489 StringRef Name = B->getName(); 490 if (!B->isUndefined() && const_cast<Regex &>(Re).match(Name)) 491 Res.push_back(B); 492 } 493 return Res; 494 } 495 496 template <class ELFT> 497 void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F, 498 const object::Archive::Symbol Sym) { 499 Symbol *S; 500 bool WasInserted; 501 StringRef Name = Sym.getName(); 502 std::tie(S, WasInserted) = insert(Name); 503 if (WasInserted) { 504 replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType); 505 return; 506 } 507 if (!S->body()->isUndefined()) 508 return; 509 510 // Weak undefined symbols should not fetch members from archives. If we were 511 // to keep old symbol we would not know that an archive member was available 512 // if a strong undefined symbol shows up afterwards in the link. If a strong 513 // undefined symbol never shows up, this lazy symbol will get to the end of 514 // the link and must be treated as the weak undefined one. We already marked 515 // this symbol as used when we added it to the symbol table, but we also need 516 // to preserve its type. FIXME: Move the Type field to Symbol. 517 if (S->isWeak()) { 518 replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type); 519 return; 520 } 521 MemoryBufferRef MBRef = F->getMember(&Sym); 522 if (!MBRef.getBuffer().empty()) 523 addFile(createObjectFile(MBRef, F->getName())); 524 } 525 526 template <class ELFT> 527 void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) { 528 Symbol *S; 529 bool WasInserted; 530 std::tie(S, WasInserted) = insert(Name); 531 if (WasInserted) { 532 replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType); 533 return; 534 } 535 if (!S->body()->isUndefined()) 536 return; 537 538 // See comment for addLazyArchive above. 539 if (S->isWeak()) { 540 replaceBody<LazyObject>(S, Name, Obj, S->body()->Type); 541 } else { 542 MemoryBufferRef MBRef = Obj.getBuffer(); 543 if (!MBRef.getBuffer().empty()) 544 addFile(createObjectFile(MBRef)); 545 } 546 } 547 548 // Process undefined (-u) flags by loading lazy symbols named by those flags. 549 template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() { 550 for (StringRef S : Config->Undefined) 551 if (auto *L = dyn_cast_or_null<Lazy>(find(S))) 552 if (InputFile *File = L->fetch()) 553 addFile(File); 554 } 555 556 // This function takes care of the case in which shared libraries depend on 557 // the user program (not the other way, which is usual). Shared libraries 558 // may have undefined symbols, expecting that the user program provides 559 // the definitions for them. An example is BSD's __progname symbol. 560 // We need to put such symbols to the main program's .dynsym so that 561 // shared libraries can find them. 562 // Except this, we ignore undefined symbols in DSOs. 563 template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { 564 for (SharedFile<ELFT> *File : SharedFiles) 565 for (StringRef U : File->getUndefinedSymbols()) 566 if (SymbolBody *Sym = find(U)) 567 if (Sym->isDefined()) 568 Sym->symbol()->ExportDynamic = true; 569 } 570 571 // This function processes --export-dynamic-symbol and --dynamic-list. 572 template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() { 573 for (StringRef S : Config->DynamicList) 574 if (SymbolBody *B = find(S)) 575 B->symbol()->ExportDynamic = true; 576 } 577 578 static void setVersionId(SymbolBody *Body, StringRef VersionName, 579 StringRef Name, uint16_t Version) { 580 if (!Body || Body->isUndefined()) { 581 if (Config->NoUndefinedVersion) 582 error("version script assignment of " + VersionName + " to symbol " + 583 Name + " failed: symbol not defined"); 584 return; 585 } 586 587 Symbol *Sym = Body->symbol(); 588 if (Sym->VersionId != Config->DefaultSymbolVersion) 589 warning("duplicate symbol " + Name + " in version script"); 590 Sym->VersionId = Version; 591 } 592 593 // Returns a map from demangled symbols to symbol objects. 594 // The relationship is 1:N instead of 1:1 because with the symbol 595 // versioning, more than one symbol may have the same name. 596 template <class ELFT> 597 std::map<std::string, std::vector<SymbolBody *>> 598 SymbolTable<ELFT>::getDemangledSyms() { 599 std::map<std::string, std::vector<SymbolBody *>> Result; 600 for (Symbol *Sym : SymVector) { 601 SymbolBody *B = Sym->body(); 602 Result[demangle(B->getName())].push_back(B); 603 } 604 return Result; 605 } 606 607 static bool hasExternCpp() { 608 for (VersionDefinition &V : Config->VersionDefinitions) 609 for (SymbolVersion Sym : V.Globals) 610 if (Sym.IsExternCpp) 611 return true; 612 return false; 613 } 614 615 static ArrayRef<SymbolBody *> 616 findDemangled(std::map<std::string, std::vector<SymbolBody *>> &D, 617 StringRef Name) { 618 auto I = D.find(Name); 619 if (I != D.end()) 620 return I->second; 621 return {}; 622 } 623 624 static std::vector<SymbolBody *> 625 findAllDemangled(const std::map<std::string, std::vector<SymbolBody *>> &D, 626 const Regex &Re) { 627 std::vector<SymbolBody *> Res; 628 for (auto &P : D) { 629 if (const_cast<Regex &>(Re).match(P.first)) 630 for (SymbolBody *Body : P.second) 631 if (!Body->isUndefined()) 632 Res.push_back(Body); 633 } 634 return Res; 635 } 636 637 // If there's only one anonymous version definition in a version 638 // script file, the script does not actullay define any symbol version, 639 // but just specifies symbols visibilities. We assume that the script was 640 // in the form of { global: foo; bar; local *; }. So, local is default. 641 // In this function, we make specified symbols global. 642 template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() { 643 std::vector<StringRef> Patterns; 644 for (SymbolVersion &Sym : Config->VersionScriptGlobals) { 645 if (hasWildcard(Sym.Name)) { 646 Patterns.push_back(Sym.Name); 647 continue; 648 } 649 if (SymbolBody *B = find(Sym.Name)) 650 B->symbol()->VersionId = VER_NDX_GLOBAL; 651 } 652 if (Patterns.empty()) 653 return; 654 Regex Re = compileGlobPatterns(Patterns); 655 std::vector<SymbolBody *> Syms = findAll(Re); 656 for (SymbolBody *B : Syms) 657 B->symbol()->VersionId = VER_NDX_GLOBAL; 658 } 659 660 // This function processes version scripts by updating VersionId 661 // member of symbols. 662 template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { 663 // Handle edge cases first. 664 if (!Config->VersionScriptGlobals.empty()) { 665 handleAnonymousVersion(); 666 return; 667 } 668 669 if (Config->VersionDefinitions.empty()) 670 return; 671 672 // Now we have version definitions, so we need to set version ids to symbols. 673 // Each version definition has a glob pattern, and all symbols that match 674 // with the pattern get that version. 675 676 // Users can use "extern C++ {}" directive to match against demangled 677 // C++ symbols. For example, you can write a pattern such as 678 // "llvm::*::foo(int, ?)". Obviously, there's no way to handle this 679 // other than trying to match a regexp against all demangled symbols. 680 // So, if "extern C++" feature is used, we demangle all known symbols. 681 std::map<std::string, std::vector<SymbolBody *>> Demangled; 682 if (hasExternCpp()) 683 Demangled = getDemangledSyms(); 684 685 // First, we assign versions to exact matching symbols, 686 // i.e. version definitions not containing any glob meta-characters. 687 for (VersionDefinition &V : Config->VersionDefinitions) { 688 for (SymbolVersion Sym : V.Globals) { 689 if (Sym.HasWildcards) 690 continue; 691 692 StringRef N = Sym.Name; 693 if (Sym.IsExternCpp) { 694 for (SymbolBody *B : findDemangled(Demangled, N)) 695 setVersionId(B, V.Name, N, V.Id); 696 continue; 697 } 698 setVersionId(find(N), V.Name, N, V.Id); 699 } 700 } 701 702 // Next, we assign versions to fuzzy matching symbols, 703 // i.e. version definitions containing glob meta-characters. 704 // Note that because the last match takes precedence over previous matches, 705 // we iterate over the definitions in the reverse order. 706 for (size_t I = Config->VersionDefinitions.size() - 1; I != (size_t)-1; --I) { 707 VersionDefinition &V = Config->VersionDefinitions[I]; 708 for (SymbolVersion &Sym : V.Globals) { 709 if (!Sym.HasWildcards) 710 continue; 711 Regex Re = compileGlobPatterns({Sym.Name}); 712 std::vector<SymbolBody *> Syms = 713 Sym.IsExternCpp ? findAllDemangled(Demangled, Re) : findAll(Re); 714 715 // Exact matching takes precendence over fuzzy matching, 716 // so we set a version to a symbol only if no version has been assigned 717 // to the symbol. This behavior is compatible with GNU. 718 for (SymbolBody *B : Syms) 719 if (B->symbol()->VersionId == Config->DefaultSymbolVersion) 720 B->symbol()->VersionId = V.Id; 721 } 722 } 723 } 724 725 template class elf::SymbolTable<ELF32LE>; 726 template class elf::SymbolTable<ELF32BE>; 727 template class elf::SymbolTable<ELF64LE>; 728 template class elf::SymbolTable<ELF64BE>; 729