Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -215,7 +215,7 @@ // be found by looking at the next one) and put the hash in a side table. struct SectionPiece { SectionPiece(size_t Off, bool Live) - : InputOff(Off), Live(Live || !Config->GcSections), OutputOff(-1) {} + : InputOff(Off), Live(Live), OutputOff(-1) {} size_t InputOff : 8 * sizeof(ssize_t) - 1; size_t Live : 1; @@ -235,8 +235,8 @@ // Mark the piece at a given offset live. Used by GC. void markLiveAt(uint64_t Offset) { - assert(this->Flags & llvm::ELF::SHF_ALLOC); - LiveOffsets.insert(Offset); + if (!arePiecesLiveByDefault()) + LiveOffsets.insert(Offset); } // Translate an offset in the input section to an offset @@ -269,6 +269,12 @@ SyntheticSection *getParent() const; private: + // We do not GC pieces of non-allocatable sections which are usually + // debug ones. Function returns true if pieces should be live by default. + bool arePiecesLiveByDefault() { + return !Config->GcSections || !(this->Flags & llvm::ELF::SHF_ALLOC); + } + void splitStrings(ArrayRef A, size_t Size); void splitNonStrings(ArrayRef A, size_t Size); Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -867,13 +867,12 @@ // null-terminated strings. void MergeInputSection::splitStrings(ArrayRef Data, size_t EntSize) { size_t Off = 0; - bool IsAlloc = this->Flags & SHF_ALLOC; while (!Data.empty()) { size_t End = findNull(Data, EntSize); if (End == StringRef::npos) fatal(toString(this) + ": string is not null terminated"); size_t Size = End + EntSize; - Pieces.emplace_back(Off, !IsAlloc); + Pieces.emplace_back(Off, arePiecesLiveByDefault()); Hashes.push_back(xxHash64(toStringRef(Data.slice(0, Size)))); Data = Data.slice(Size); Off += Size; @@ -886,10 +885,9 @@ size_t EntSize) { size_t Size = Data.size(); assert((Size % EntSize) == 0); - bool IsAlloc = this->Flags & SHF_ALLOC; for (unsigned I = 0, N = Size; I != N; I += EntSize) { Hashes.push_back(xxHash64(toStringRef(Data.slice(I, EntSize)))); - Pieces.emplace_back(I, !IsAlloc); + Pieces.emplace_back(I, arePiecesLiveByDefault()); } } @@ -914,7 +912,7 @@ else splitNonStrings(Data, EntSize); - if (Config->GcSections && (this->Flags & SHF_ALLOC)) + if (!arePiecesLiveByDefault()) for (uint64_t Off : LiveOffsets) this->getSectionPiece(Off)->Live = true; } Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -162,9 +162,9 @@ scanEhFrameSection(EH, EH.template rels(), Fn); } -// We do not garbage-collect two types of sections: -// 1) Sections used by the loader (.init, .fini, .ctors, .dtors or .jcr) -// 2) Non-allocatable sections which typically contain debugging information +// 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. template static bool isReserved(InputSectionBase *Sec) { switch (Sec->Type) { case SHT_FINI_ARRAY: @@ -173,9 +173,6 @@ case SHT_PREINIT_ARRAY: return true; default: - if (!(Sec->Flags & SHF_ALLOC)) - return true; - StringRef S = Sec->Name; return S.startswith(".ctors") || S.startswith(".dtors") || S.startswith(".init") || S.startswith(".fini") || @@ -198,10 +195,6 @@ if (Sec == &InputSection::Discarded) return; - // We don't gc non alloc sections. - if (!(Sec->Flags & SHF_ALLOC)) - return; - // Usually, a whole section is marked as live or dead, but in mergeable // (splittable) sections, each piece of data has independent liveness bit. // So we explicitly tell it which offset is in use.