[ELF] --gc-sections: combine two iterations over inputSections

There is a slight speed-up.
This commit is contained in:
Fangrui Song 2021-12-23 09:53:08 -08:00
parent 4bf31659fa
commit 4374824ccf
1 changed files with 34 additions and 13 deletions

View File

@ -244,8 +244,6 @@ template <class ELFT> void MarkLive<ELFT>::run() {
for (StringRef s : script->referencedSymbols)
markSymbol(symtab->find(s));
// Preserve special sections and those which are specified in linker
// script KEEP command.
for (InputSectionBase *sec : inputSections) {
// Mark .eh_frame sections as live because there are usually no relocations
// that point to .eh_frames. Otherwise, the garbage collector would drop
@ -259,6 +257,7 @@ template <class ELFT> void MarkLive<ELFT>::run() {
scanEhFrameSection(*eh, rels.rels);
else if (rels.relas.size())
scanEhFrameSection(*eh, rels.relas);
continue;
}
if (sec->flags & SHF_GNU_RETAIN) {
@ -268,6 +267,39 @@ template <class ELFT> void MarkLive<ELFT>::run() {
if (sec->flags & SHF_LINK_ORDER)
continue;
// Usually, 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.) When a
// non-SHF_ALLOC section is retained, we also retain sections dependent on
// it.
//
// Note on SHF_LINK_ORDER: Such sections contain metadata and they
// have a reverse dependency on the InputSection they are linked with.
// We are able to garbage collect them.
//
// 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.
//
// Note on nextInSectionGroup: The ELF spec says that group sections are
// included or omitted as a unit. We take the interpretation that:
//
// - Group members (nextInSectionGroup != nullptr) are subject to garbage
// collection.
// - Groups members are retained or discarded as a unit.
if (!(sec->flags & SHF_ALLOC)) {
bool isRel = sec->type == SHT_REL || sec->type == SHT_RELA;
if (!isRel && !sec->nextInSectionGroup) {
sec->markLive();
for (InputSection *isec : sec->dependentSections)
isec->markLive();
}
}
// Preserve special sections and those which are specified in linker
// script KEEP command.
if (isReserved(sec) || script->shouldKeep(sec)) {
enqueue(sec, 0);
} else if ((!config->zStartStopGC || sec->name.startswith("__libc_")) &&
@ -377,17 +409,6 @@ template <class ELFT> void elf::markLive() {
// - Group members (nextInSectionGroup != nullptr) are subject to garbage
// collection.
// - Groups members are retained or discarded as a unit.
for (InputSectionBase *sec : inputSections) {
bool isAlloc = (sec->flags & SHF_ALLOC);
bool isLinkOrder = (sec->flags & SHF_LINK_ORDER);
bool isRel = (sec->type == SHT_REL || sec->type == SHT_RELA);
if (!isAlloc && !isLinkOrder && !isRel && !sec->nextInSectionGroup) {
sec->markLive();
for (InputSection *isec : sec->dependentSections)
isec->markLive();
}
}
// Follow the graph to mark all live sections.
for (unsigned curPart = 1; curPart <= partitions.size(); ++curPart)