Index: lld/trunk/ELF/MarkLive.cpp =================================================================== --- lld/trunk/ELF/MarkLive.cpp +++ lld/trunk/ELF/MarkLive.cpp @@ -61,7 +61,8 @@ } template -static ResolvedReloc resolveReloc(InputSection *Sec, RelT &Rel) { +static ResolvedReloc resolveReloc(InputSectionBase *Sec, + RelT &Rel) { SymbolBody &B = Sec->getFile()->getRelocTargetSym(Rel); auto *D = dyn_cast>(&B); if (!D || !D->Section) @@ -72,24 +73,38 @@ return {D->Section->Repl, Offset}; } +template +static void run(ELFFile &Obj, InputSectionBase *Sec, + Elf_Shdr *RelSec, std::function)> Fn) { + if (RelSec->sh_type == SHT_RELA) { + for (const typename ELFT::Rela &RI : Obj.relas(RelSec)) + Fn(resolveReloc(Sec, RI)); + } else { + for (const typename ELFT::Rel &RI : Obj.rels(RelSec)) + Fn(resolveReloc(Sec, RI)); + } +} + // Calls Fn for each section that Sec refers to via relocations. template static void forEachSuccessor(InputSection *Sec, std::function)> Fn) { - typedef typename ELFT::Rel Elf_Rel; - typedef typename ELFT::Rela Elf_Rela; - typedef typename ELFT::Shdr Elf_Shdr; - ELFFile &Obj = Sec->getFile()->getObj(); - for (const Elf_Shdr *RelSec : Sec->RelocSections) { - if (RelSec->sh_type == SHT_RELA) { - for (const Elf_Rela &RI : Obj.relas(RelSec)) - Fn(resolveReloc(Sec, RI)); - } else { - for (const Elf_Rel &RI : Obj.rels(RelSec)) - Fn(resolveReloc(Sec, RI)); - } - } + for (const typename ELFT::Shdr *RelSec : Sec->RelocSections) + run(Obj, Sec, RelSec, Fn); +} + +template static void scanEhFrameSection(EHInputSection &EH) { + if (!EH.RelocSection) + return; + ELFFile &EObj = EH.getFile()->getObj(); + run(EObj, &EH, EH.RelocSection, [&](ResolvedReloc R) { + if (!R.Sec || R.Sec == &InputSection::Discarded) + return; + if (R.Sec->getSectionHdr()->sh_flags & SHF_EXECINSTR) + return; + R.Sec->Live = true; + }); } // Sections listed below are special because they are used by the loader @@ -160,9 +175,15 @@ // script KEEP command. for (const std::unique_ptr> &F : Symtab->getObjectFiles()) for (InputSectionBase *Sec : F->getSections()) - if (Sec && Sec != &InputSection::Discarded) + if (Sec && Sec != &InputSection::Discarded) { + // .eh_frame is always marked as live now, but also it can reference to + // sections that contain personality. We preserve all non-text sections + // referred by .eh_frame here. + if (auto *EH = dyn_cast_or_null>(Sec)) + scanEhFrameSection(*EH); if (isReserved(Sec) || Script::X->shouldKeep(Sec)) Enqueue({Sec, 0}); + } // Mark all reachable sections. while (!Q.empty()) Index: lld/trunk/test/ELF/eh-frame-gc.s =================================================================== --- lld/trunk/test/ELF/eh-frame-gc.s +++ lld/trunk/test/ELF/eh-frame-gc.s @@ -0,0 +1,20 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o +# RUN: ld.lld -shared --gc-sections %t.o -o %t +# RUN: llvm-readobj -s %t | FileCheck %s + +## Check that section containing personality is +## not garbage collected. +# CHECK: Sections [ +# CHECK: Name: .test_personality_section + +.text +.globl foo +.type foo,@function +foo: + .cfi_startproc + .cfi_personality 155, DW.ref.__gxx_personality_v0 + .cfi_endproc + +.section .test_personality_section +DW.ref.__gxx_personality_v0: