forked from OSchip/llvm-project
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:
parent
e9ea08a097
commit
a1b79dff2a
|
@ -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>();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue