//===- MarkLive.cpp -------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements --gc-sections, which is a feature to remove unused // sections from output. Unused sections are sections that are not reachable // from known GC-root symbols or sections. Naturally the feature is // implemented as a mark-sweep garbage collector. // // Here's how it works. Each InputSectionBase has a "Live" bit. The bit is off // by default. Starting with GC-root symbols or sections, markLive function // defined in this file visits all reachable sections to set their Live // bits. Writer will then ignore sections whose Live bits are off, so that // such sections are not included into output. // //===----------------------------------------------------------------------===// #include "MarkLive.h" #include "InputFiles.h" #include "InputSection.h" #include "LinkerScript.h" #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" #include "lld/Common/CommonLinkerContext.h" #include "lld/Common/Strings.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Object/ELF.h" #include "llvm/Support/TimeProfiler.h" #include <vector> usingnamespacellvm; usingnamespacellvm::ELF; usingnamespacellvm::object; usingnamespacellvm::support::endian; usingnamespacelld; usingnamespacelld::elf; namespace { template <class ELFT> class MarkLive { … }; } // namespace template <class ELFT> static uint64_t getAddend(Ctx &ctx, InputSectionBase &sec, const typename ELFT::Rel &rel) { … } template <class ELFT> static uint64_t getAddend(Ctx &, InputSectionBase &sec, const typename ELFT::Rela &rel) { … } // Currently, we assume all input CREL relocations have an explicit addend. template <class ELFT> static uint64_t getAddend(Ctx &, InputSectionBase &sec, const typename ELFT::Crel &rel) { … } template <class ELFT> template <class RelTy> void MarkLive<ELFT>::resolveReloc(InputSectionBase &sec, RelTy &rel, bool fromFDE) { … } // The .eh_frame section is an unfortunate special case. // The section is divided in CIEs and FDEs and the relocations it can have are // * CIEs can refer to a personality function. // * FDEs can refer to a LSDA // * FDEs refer to the function they contain information about // The last kind of relocation cannot keep the referred section alive, or they // would keep everything alive in a common object file. In fact, each FDE is // alive if the section it refers to is alive. // To keep things simple, in here we just ignore the last relocation kind. The // other two keep the referred section alive. // // A possible improvement would be to fully process .eh_frame in the middle of // the gc pass. With that we would be able to also gc some sections holding // LSDAs and personality functions if we found that they were unused. template <class ELFT> template <class RelTy> void MarkLive<ELFT>::scanEhFrameSection(EhInputSection &eh, ArrayRef<RelTy> rels) { … } // Some sections are used directly by the loader, so they should never be // garbage-collected. This function returns true if a given section is such // section. static bool isReserved(InputSectionBase *sec) { … } template <class ELFT> void MarkLive<ELFT>::enqueue(InputSectionBase *sec, uint64_t offset) { … } template <class ELFT> void MarkLive<ELFT>::markSymbol(Symbol *sym) { … } // 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 MarkLive<ELFT>::run() { … } template <class ELFT> void MarkLive<ELFT>::mark() { … } // Move the sections for some symbols to the main partition, specifically ifuncs // (because they can result in an IRELATIVE being added to the main partition's // GOT, which means that the ifunc must be available when the main partition is // loaded) and TLS symbols (because we only know how to correctly process TLS // relocations for the main partition). // // We also need to move sections whose names are C identifiers that are referred // to from __start_/__stop_ symbols because there will only be one set of // symbols for the whole program. template <class ELFT> void MarkLive<ELFT>::moveToMain() { … } // Before calling this function, Live bits are off for all // input sections. This function make some or all of them on // so that they are emitted to the output file. template <class ELFT> void elf::markLive(Ctx &ctx) { … } template void elf::markLive<ELF32LE>(Ctx &); template void elf::markLive<ELF32BE>(Ctx &); template void elf::markLive<ELF64LE>(Ctx &); template void elf::markLive<ELF64BE>(Ctx &);