diff options
author | Fangrui Song <i@maskray.me> | 2021-02-26 16:38:44 -0800 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2021-02-26 16:38:44 -0800 |
commit | 47c5576d7d586624c38f76bd3168e05f6ef1f838 (patch) | |
tree | b8d955f1c3f64e7cf994818939be3b8e1dbbaa3a /llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | |
parent | 8afdacba9dcd36fc838eb86fca86f7f903040030 (diff) | |
download | llvm-47c5576d7d586624c38f76bd3168e05f6ef1f838.zip llvm-47c5576d7d586624c38f76bd3168e05f6ef1f838.tar.gz llvm-47c5576d7d586624c38f76bd3168e05f6ef1f838.tar.bz2 |
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
Diffstat (limited to 'llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp')
-rw-r--r-- | llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 36 |
1 files changed, 28 insertions, 8 deletions
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<GlobalValue *, 4> Vec; + collectUsedGlobalVariables(M, Vec, false); + for (GlobalValue *GV : Vec) + if (auto *GO = dyn_cast<GlobalObject>(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( |