From af90d54660dae0fdd61e918e3d2d797e255c7c7d Mon Sep 17 00:00:00 2001 From: George Rimar Date: Mon, 2 May 2016 13:49:42 +0000 Subject: [PATCH] [ELF] - keep alive all non-text sections referenced by .eh_frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch implements one of suggestions from Rafael Ávila de Espíndola, to fix segfault after section that contains personality being garbage collected. Suggestion was just to keep alive all non executable sections referenced by .eh_frame. This fixes PR27529. Differential revision: http://reviews.llvm.org/D19656 llvm-svn: 268228 --- lld/ELF/MarkLive.cpp | 51 +++++++++++++++++++++++++++----------- lld/test/ELF/eh-frame-gc.s | 20 +++++++++++++++ 2 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 lld/test/ELF/eh-frame-gc.s diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 0c9fedb3932d..b6052697e1ad 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -61,7 +61,8 @@ static typename ELFT::uint getAddend(InputSectionBase *Sec, } 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 @@ static ResolvedReloc resolveReloc(InputSection *Sec, RelT &Rel) { 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 @@ template void elf::markLive(SymbolTable *Symtab) { // 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()) diff --git a/lld/test/ELF/eh-frame-gc.s b/lld/test/ELF/eh-frame-gc.s new file mode 100644 index 000000000000..b2e21f497f41 --- /dev/null +++ b/lld/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: