Ejemplo n.º 1
0
// 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;
  }
}
Ejemplo n.º 2
0
// 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);
}