// Versions are usually assigned to symbols using version scripts, // but there's another way to assign versions to symbols. // If a symbol name contains '@', the string after it is not // actually a part of the symbol name but specifies a version. // This function takes care of it. template <class ELFT> void SymbolTable<ELFT>::scanSymbolVersions() { if (Config->VersionDefinitions.empty()) return; int MaxVersionLen = getMaxVersionLen(); // Unfortunately there's no way other than iterating over all // symbols to look for '@' characters in symbol names. // So this is inherently slow. A good news is that we do this // only when versions have been defined. for (Symbol *Sym : SymVector) { // Symbol versions for exported symbols are by nature // only for defined global symbols. SymbolBody *B = Sym->body(); if (!B->isDefined()) continue; uint8_t Visibility = B->getVisibility(); if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) continue; // Look for '@' in the symbol name. StringRef Name; uint16_t Version; std::tie(Name, Version) = getSymbolVersion(B, MaxVersionLen); if (Name.empty()) continue; B->setName(Name); Sym->VersionId = Version; } }
// This is the main function of the garbage collector. // Starting from GC-root sections, this function visits all reachable // sections to set their "Live" bits. template <class ELFT> void elf::markLive(SymbolTable<ELFT> *Symtab) { SmallVector<InputSection<ELFT> *, 256> Q; auto Enqueue = [&](InputSectionBase<ELFT> *Sec) { if (!Sec || Sec->Live) return; Sec->Live = true; if (InputSection<ELFT> *S = dyn_cast<InputSection<ELFT>>(Sec)) Q.push_back(S); }; auto MarkSymbol = [&](SymbolBody *Sym) { if (Sym) if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&Sym->repl())) Enqueue(D->Section); }; // Add GC root symbols. MarkSymbol(Config->EntrySym); MarkSymbol(Symtab->find(Config->Init)); MarkSymbol(Symtab->find(Config->Fini)); for (StringRef S : Config->Undefined) MarkSymbol(Symtab->find(S)); // Preserve externally-visible symbols if the symbols defined by this // file can interrupt other ELF file's symbols at runtime. if (Config->Shared || Config->ExportDynamic) { for (const std::pair<StringRef, Symbol *> &P : Symtab->getSymbols()) { SymbolBody *B = P.second->Body; if (B->getVisibility() == STV_DEFAULT) MarkSymbol(B); } } // Preserve special sections and those which are specified in linker // script KEEP command. for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles()) for (InputSectionBase<ELFT> *Sec : F->getSections()) if (Sec && Sec != &InputSection<ELFT>::Discarded) if (isReserved(Sec) || Script->shouldKeep<ELFT>(Sec)) Enqueue(Sec); // Mark all reachable sections. while (!Q.empty()) forEachSuccessor<ELFT>(Q.pop_back_val(), Enqueue); }