Handle input section liveness only in MarkLive.cpp.

The condition whether a section is alive or not by default
is becoming increasingly complex, so the decision of garbage
collection is spreading over InputSection.h and MarkLive.cpp,
which is not a good state.

This moves the code to MarkLive.cpp, to keep the file the central
place to make decisions about garbage collection.

llvm-svn: 315384
This commit is contained in:
Rui Ueyama 2017-10-10 22:59:32 +00:00
parent e9ea08a097
commit a1b79dff2a
5 changed files with 47 additions and 34 deletions

View File

@ -1106,8 +1106,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
// Do size optimizations: garbage collection, merging of SHF_MERGE sections
// and identical code folding.
if (Config->GcSections)
markLive<ELFT>();
markLive<ELFT>();
decompressAndMergeSections();
if (Config->ICF)
doIcf<ELFT>();

View File

@ -482,20 +482,6 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
if (Config->Strip != StripPolicy::None && Name.startswith(".debug"))
return &InputSection::Discarded;
// If -gdb-index is given, LLD creates .gdb_index section, and that
// section serves the same purpose as .debug_gnu_pub{names,types} sections.
// If that's the case, we want to eliminate .debug_gnu_pub{names,types}
// because they are redundant and can waste large amount of disk space
// (for example, they are about 400 MiB in total for a clang debug build.)
// We still create the section and mark it dead so that the gdb index code
// can use the InputSection to access the data.
if (Config->GdbIndex &&
(Name == ".debug_gnu_pubnames" || Name == ".debug_gnu_pubtypes")) {
auto *Ret = make<InputSection>(this, &Sec, Name);
Script->discard({Ret});
return Ret;
}
// The linkonce feature is a sort of proto-comdat. Some glibc i386 object
// files contain definitions of symbol "__x86.get_pc_thunk.bx" in linkonce
// sections. Drop those sections to avoid duplicate symbol errors.

View File

@ -76,22 +76,6 @@ static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> *File,
return check(File->getObj().getSectionContents(Hdr));
}
// Return true if a section with given section flags is live (will never be
// GCed) by default. If a section can be GCed, this function returns false.
static bool isLiveByDefault(uint64_t Flags, uint32_t Type) {
// If GC is enabled, all memory-mapped sections are subject of GC.
if (!Config->GcSections)
return true;
if (Flags & SHF_ALLOC)
return false;
// Besides that, relocation sections can also be GCed because their
// relocation target sections may be GCed. This doesn't really matter
// in most cases because the linker usually consumes relocation
// sections instead of emitting them, but -emit-reloc needs this.
return Type != SHT_REL && Type != SHT_RELA;
}
InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,
uint32_t Type, uint64_t Entsize,
uint32_t Link, uint32_t Info,
@ -100,7 +84,6 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,
: SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info,
Link),
File(File), Data(Data), Repl(this) {
Live = isLiveByDefault(Flags, Type);
Assigned = false;
NumRelocations = 0;
AreRelocsRela = false;

View File

@ -186,7 +186,7 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) {
// 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() {
template <class ELFT> static void doGcSections() {
SmallVector<InputSection *, 256> Q;
CNamedSections.clear();
@ -261,6 +261,42 @@ template <class ELFT> void elf::markLive() {
forEachSuccessor<ELFT>(*Q.pop_back_val(), Enqueue);
}
// 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() {
// If -gc-sections is missing, no sections are removed.
if (!Config->GcSections) {
for (InputSectionBase *Sec : InputSections)
Sec->Live = true;
return;
}
// The -gc-sections option works only for SHF_ALLOC sections
// (sections that are memory-mapped at runtime). So we can
// unconditionally make non-SHF_ALLOC sections alive.
//
// Non SHF_ALLOC sections are not removed even if they are
// unreachable through relocations because reachability is not
// a good signal whether they are garbage or not (e.g. there is
// usually no section referring to a .comment section, but we
// want to keep it.)
//
// Note on SHF_REL{,A}: Such sections reach here only when -r
// or -emit-reloc were given. And they are subject of garbage
// collection because, if we remove a text section, we also
// remove its relocation section.
for (InputSectionBase *Sec : InputSections) {
bool IsAlloc = (Sec->Flags & SHF_ALLOC);
bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA);
if (!IsAlloc && !IsRel)
Sec->Live = true;
}
// Follow the graph to mark all live sections.
doGcSections<ELFT>();
}
template void elf::markLive<ELF32LE>();
template void elf::markLive<ELF32BE>();
template void elf::markLive<ELF64LE>();

View File

@ -1831,6 +1831,7 @@ std::vector<std::vector<uint32_t>> GdbIndexSection::createCuVectors() {
}
template <class ELFT> GdbIndexSection *elf::createGdbIndex() {
// Gather debug info to create a .gdb_index section.
std::vector<InputSection *> Sections = getDebugInfoSections();
std::vector<GdbIndexChunk> Chunks(Sections.size());
@ -1844,6 +1845,14 @@ template <class ELFT> GdbIndexSection *elf::createGdbIndex() {
Chunks[I].NamesAndTypes = readPubNamesAndTypes(Dwarf);
});
// .debug_gnu_pub{names,types} are useless in executables.
// They are present in input object files solely for creating
// a .gdb_index. So we can remove it from the output.
for (InputSectionBase *S : InputSections)
if (S->Name == ".debug_gnu_pubnames" || S->Name == ".debug_gnu_pubtypes")
S->Live = false;
// Create a .gdb_index and returns it.
return make<GdbIndexSection>(std::move(Chunks));
}