From 47c5576d7d586624c38f76bd3168e05f6ef1f838 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 26 Feb 2021 16:38:44 -0800 Subject: ELF: Create unique SHF_GNU_RETAIN sections for llvm.used global objects If a global object is listed in `@llvm.used`, place it in a unique section with the `SHF_GNU_RETAIN` flag. The section is a GC root under `ld --gc-sections` with LLD>=13 or GNU ld>=2.36. For front ends which do not expect to see multiple sections of the same name, consider emitting `@llvm.compiler.used` instead of `@llvm.used`. SHF_GNU_RETAIN is restricted to ELFOSABI_GNU and ELFOSABI_FREEBSD in binutils. We don't do the restriction - see the rationale in D95749. The integrated assembler has supported SHF_GNU_RETAIN since D95730. GNU as>=2.36 supports section flag 'R'. We don't need to worry about GNU ld support because older GNU ld just ignores the unknown SHF_GNU_RETAIN. With this change, `__attribute__((retain))` functions/variables emitted by clang will get the SHF_GNU_RETAIN flag. Differential Revision: https://reviews.llvm.org/D97448 --- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 36 ++++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp') diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 8f74866..f1729d1 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -293,6 +293,14 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, } } +void TargetLoweringObjectFileELF::getModuleMetadata(Module &M) { + SmallVector Vec; + collectUsedGlobalVariables(M, Vec, false); + for (GlobalValue *GV : Vec) + if (auto *GO = dyn_cast(GV)) + Used.insert(GO); +} + void TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer, Module &M) const { auto &C = getContext(); @@ -687,9 +695,15 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal( // MD_associated in a unique section. unsigned UniqueID = MCContext::GenericSectionID; const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM); - if (GO->getMetadata(LLVMContext::MD_associated)) { + const bool Associated = GO->getMetadata(LLVMContext::MD_associated); + const bool Retain = Used.count(GO); + if (Associated || Retain) { UniqueID = NextUniqueID++; - Flags |= ELF::SHF_LINK_ORDER; + if (Associated) + Flags |= ELF::SHF_LINK_ORDER; + if (Retain && (getContext().getAsmInfo()->useIntegratedAssembler() || + getContext().getAsmInfo()->binutilsIsAtLeast(2, 36))) + Flags |= ELF::SHF_GNU_RETAIN; } else { if (getContext().getAsmInfo()->useIntegratedAssembler() || getContext().getAsmInfo()->binutilsIsAtLeast(2, 35)) { @@ -802,13 +816,18 @@ static MCSectionELF *selectELFSectionForGlobal( static MCSection *selectELFSectionForGlobal( MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang, - const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags, - unsigned *NextUniqueID) { + const TargetMachine &TM, bool Retain, bool EmitUniqueSection, + unsigned Flags, unsigned *NextUniqueID) { const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM); if (LinkedToSym) { EmitUniqueSection = true; Flags |= ELF::SHF_LINK_ORDER; } + if (Retain && (Ctx.getAsmInfo()->useIntegratedAssembler() || + Ctx.getAsmInfo()->binutilsIsAtLeast(2, 36))) { + EmitUniqueSection = true; + Flags |= ELF::SHF_GNU_RETAIN; + } MCSectionELF *Section = selectELFSectionForGlobal( Ctx, GO, Kind, Mang, TM, EmitUniqueSection, Flags, @@ -832,16 +851,17 @@ MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal( } EmitUniqueSection |= GO->hasComdat(); return selectELFSectionForGlobal(getContext(), GO, Kind, getMangler(), TM, - EmitUniqueSection, Flags, &NextUniqueID); + Used.count(GO), EmitUniqueSection, Flags, + &NextUniqueID); } MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction( const Function &F, const TargetMachine &TM) const { SectionKind Kind = SectionKind::getText(); unsigned Flags = getELFSectionFlags(Kind); - return selectELFSectionForGlobal(getContext(), &F, Kind, getMangler(), TM, - /* EmitUniqueSection = */ true, Flags, - &NextUniqueID); + return selectELFSectionForGlobal( + getContext(), &F, Kind, getMangler(), TM, Used.count(&F), + /*EmitUniqueSection=*/true, Flags, &NextUniqueID); } MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable( -- cgit v1.1