[lld] r252790 - Add support for processing .eh_frame.

Hal Finkel via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 27 12:22:04 PST 2015


Hi Rafael,

You had suggested that I model proper PPC64 .opd support after this implementation; could you please elaborate?

To summarize, the "special" part about the .opd section is that it can legally contain relocations to discarded (comdat) sections, and we need to be able to find the corresponding non-discarded section.

You had suggested that the right logic for this might be that, when part of an .opd section references a discarded section, to discard it as through the input had multiple .opd sections (that were part of the proper comdat groups).

Thanks again,
Hal

----- Original Message -----
> From: "Rafael Espindola via llvm-commits" <llvm-commits at lists.llvm.org>
> To: llvm-commits at lists.llvm.org
> Sent: Wednesday, November 11, 2015 1:54:15 PM
> Subject: [lld] r252790 - Add support for processing .eh_frame.
> 
> Author: rafael
> Date: Wed Nov 11 13:54:14 2015
> New Revision: 252790
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=252790&view=rev
> Log:
> Add support for processing .eh_frame.
> 
> This adds support for:
> * Uniquing CIEs
> * Dropping FDEs that point to dropped sections
> 
> It drops 657 488 bytes from the .eh_frame of a Release+Asserts clang.
> 
> The link time impact is smallish. Linking clang with a
> Release+Asserts
> lld goes from 0.488064805 seconds to 0.504763060 seconds (1.034 X
> slower).
> 
> Added:
>     lld/trunk/test/elf2/Inputs/invalid-multiple-eh-relocs.elf
>     lld/trunk/test/elf2/eh-frame-merge.s
>     lld/trunk/test/elf2/eh-frame-plt.s
>     lld/trunk/test/elf2/invalid-cie-length.s
>     lld/trunk/test/elf2/invalid-cie-length2.s
>     lld/trunk/test/elf2/invalid-cie-reference.s
>     lld/trunk/test/elf2/invalid-fde-rel.s
> Modified:
>     lld/trunk/ELF/InputFiles.cpp
>     lld/trunk/ELF/InputSection.cpp
>     lld/trunk/ELF/InputSection.h
>     lld/trunk/ELF/OutputSections.cpp
>     lld/trunk/ELF/OutputSections.h
>     lld/trunk/ELF/Writer.cpp
>     lld/trunk/test/elf2/invalid-elf.test
> 
> Modified: lld/trunk/ELF/InputFiles.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=252790&r1=252789&r2=252790&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputFiles.cpp (original)
> +++ lld/trunk/ELF/InputFiles.cpp Wed Nov 11 13:54:14 2015
> @@ -205,19 +205,29 @@ void elf2::ObjectFile<ELFT>::initializeS
>            Sections[RelocatedSectionIndex];
>        if (!RelocatedSection)
>          error("Unsupported relocation reference");
> -      if (auto *S = dyn_cast<InputSection<ELFT>>(RelocatedSection))
> +      if (auto *S = dyn_cast<InputSection<ELFT>>(RelocatedSection))
> {
>          S->RelocSections.push_back(&Sec);
> -      else
> +      } else if (auto *S =
> dyn_cast<EHInputSection<ELFT>>(RelocatedSection)) {
> +        if (S->RelocSection)
> +          error("Multiple relocation sections to .eh_frame are not
> supported");
> +        S->RelocSection = &Sec;
> +      } else {
>          error("Relocations pointing to SHF_MERGE are not
>          supported");
> +      }
>        break;
>      }
> -    default:
> -      if (shouldMerge<ELFT>(Sec))
> +    default: {
> +      ErrorOr<StringRef> NameOrErr =
> this->ELFObj.getSectionName(&Sec);
> +      error(NameOrErr);
> +      if (*NameOrErr == ".eh_frame")
> +        Sections[I] = new (this->Alloc) EHInputSection<ELFT>(this,
> &Sec);
> +      else if (shouldMerge<ELFT>(Sec))
>          Sections[I] = new (this->Alloc)
>          MergeInputSection<ELFT>(this, &Sec);
>        else
>          Sections[I] = new (this->Alloc) InputSection<ELFT>(this,
>          &Sec);
>        break;
>      }
> +    }
>    }
>  }
>  
> 
> Modified: lld/trunk/ELF/InputSection.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=252790&r1=252789&r2=252790&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputSection.cpp (original)
> +++ lld/trunk/ELF/InputSection.cpp Wed Nov 11 13:54:14 2015
> @@ -47,6 +47,8 @@ InputSectionBase<ELFT>::getOffset(uintX_
>    switch (SectionKind) {
>    case Regular:
>      return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
> +  case EHFrame:
> +    return cast<EHInputSection<ELFT>>(this)->getOffset(Offset);
>    case Merge:
>      return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
>    }
> @@ -93,13 +95,17 @@ template <class ELFT>
>  template <bool isRela>
>  void InputSectionBase<ELFT>::relocate(
>      uint8_t *Buf, uint8_t *BufEnd,
> -    iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels, uintX_t
> BaseAddr) {
> +    iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
>    typedef Elf_Rel_Impl<ELFT, isRela> RelType;
>    for (const RelType &RI : Rels) {
>      uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
>      uint32_t Type = RI.getType(Config->Mips64EL);
> -    uint8_t *BufLoc = Buf + RI.r_offset;
> -    uintX_t AddrLoc = BaseAddr + RI.r_offset;
> +    uintX_t Offset = getOffset(RI.r_offset);
> +    if (Offset == (uintX_t)-1)
> +      continue;
> +
> +    uint8_t *BufLoc = Buf + Offset;
> +    uintX_t AddrLoc = OutSec->getVA() + Offset;
>  
>      if (Type == Target->getTlsLocalDynamicReloc()) {
>        Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
> @@ -146,30 +152,59 @@ template <class ELFT> void InputSection<
>    memcpy(Buf + OutSecOff, Data.data(), Data.size());
>  
>    ELFFile<ELFT> &EObj = this->File->getObj();
> -  uint8_t *Base = Buf + OutSecOff;
> -  uintX_t BaseAddr = this->OutSec->getVA() + OutSecOff;
> +  uint8_t *BufEnd = Buf + OutSecOff + Data.size();
>    // Iterate over all relocation sections that apply to this
>    section.
> -  for (const Elf_Shdr *RelSec : RelocSections) {
> +  for (const Elf_Shdr *RelSec : this->RelocSections) {
>      if (RelSec->sh_type == SHT_RELA)
> -      this->relocate(Base, Base + Data.size(), EObj.relas(RelSec),
> BaseAddr);
> +      this->relocate(Buf, BufEnd, EObj.relas(RelSec));
>      else
> -      this->relocate(Base, Base + Data.size(), EObj.rels(RelSec),
> BaseAddr);
> +      this->relocate(Buf, BufEnd, EObj.rels(RelSec));
>    }
>  }
>  
>  template <class ELFT>
> +SplitInputSection<ELFT>::SplitInputSection(
> +    ObjectFile<ELFT> *File, const Elf_Shdr *Header,
> +    typename InputSectionBase<ELFT>::Kind SectionKind)
> +    : InputSectionBase<ELFT>(File, Header, SectionKind) {}
> +
> +template <class ELFT>
> +EHInputSection<ELFT>::EHInputSection(ObjectFile<ELFT> *F,
> +                                     const Elf_Shdr *Header)
> +    : SplitInputSection<ELFT>(F, Header,
> InputSectionBase<ELFT>::EHFrame) {}
> +
> +template <class ELFT>
> +bool EHInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S)
> {
> +  return S->SectionKind == InputSectionBase<ELFT>::EHFrame;
> +}
> +
> +template <class ELFT>
> +typename EHInputSection<ELFT>::uintX_t
> +EHInputSection<ELFT>::getOffset(uintX_t Offset) {
> +  std::pair<uintX_t, uintX_t> *I =
> this->getRangeAndSize(Offset).first;
> +  uintX_t Base = I->second;
> +  if (Base == size_t(-1))
> +    return -1; // Not in the output
> +
> +  uintX_t Addend = Offset - I->first;
> +  return Base + Addend;
> +}
> +
> +template <class ELFT>
>  MergeInputSection<ELFT>::MergeInputSection(ObjectFile<ELFT> *F,
>                                             const Elf_Shdr *Header)
> -    : InputSectionBase<ELFT>(F, Header, Base::Merge) {}
> +    : SplitInputSection<ELFT>(F, Header,
> InputSectionBase<ELFT>::Merge) {}
>  
>  template <class ELFT>
>  bool MergeInputSection<ELFT>::classof(const InputSectionBase<ELFT>
>  *S) {
> -  return S->SectionKind == Base::Merge;
> +  return S->SectionKind == InputSectionBase<ELFT>::Merge;
>  }
>  
>  template <class ELFT>
> -typename MergeInputSection<ELFT>::uintX_t
> -MergeInputSection<ELFT>::getOffset(uintX_t Offset) {
> +std::pair<std::pair<typename ELFFile<ELFT>::uintX_t,
> +                    typename ELFFile<ELFT>::uintX_t> *,
> +          typename ELFFile<ELFT>::uintX_t>
> +SplitInputSection<ELFT>::getRangeAndSize(uintX_t Offset) {
>    ArrayRef<uint8_t> D = this->getSectionData();
>    StringRef Data((const char *)D.data(), D.size());
>    uintX_t Size = Data.size();
> @@ -184,6 +219,16 @@ MergeInputSection<ELFT>::getOffset(uintX
>        });
>    uintX_t End = I == Offsets.end() ? Data.size() : I->first;
>    --I;
> +  return std::make_pair(&*I, End);
> +}
> +
> +template <class ELFT>
> +typename MergeInputSection<ELFT>::uintX_t
> +MergeInputSection<ELFT>::getOffset(uintX_t Offset) {
> +  std::pair<std::pair<uintX_t, uintX_t> *, size_t> T =
> +      this->getRangeAndSize(Offset);
> +  std::pair<uintX_t, uintX_t> *I = T.first;
> +  uintX_t End = T.second;
>    uintX_t Start = I->first;
>  
>    // Compute the Addend and if the Base is cached, return.
> @@ -193,6 +238,8 @@ MergeInputSection<ELFT>::getOffset(uintX
>      return Base + Addend;
>  
>    // Map the base to the offset in the output section and cashe it.
> +  ArrayRef<uint8_t> D = this->getSectionData();
> +  StringRef Data((const char *)D.data(), D.size());
>    StringRef Entry = Data.substr(Start, End - Start);
>    Base =
>        static_cast<MergeOutputSection<ELFT>
>        *>(this->OutSec)->getOffset(Entry);
> @@ -211,6 +258,11 @@ template class InputSection<object::ELF3
>  template class InputSection<object::ELF64LE>;
>  template class InputSection<object::ELF64BE>;
>  
> +template class EHInputSection<object::ELF32LE>;
> +template class EHInputSection<object::ELF32BE>;
> +template class EHInputSection<object::ELF64LE>;
> +template class EHInputSection<object::ELF64BE>;
> +
>  template class MergeInputSection<object::ELF32LE>;
>  template class MergeInputSection<object::ELF32BE>;
>  template class MergeInputSection<object::ELF64LE>;
> 
> Modified: lld/trunk/ELF/InputSection.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=252790&r1=252789&r2=252790&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputSection.h (original)
> +++ lld/trunk/ELF/InputSection.h Wed Nov 11 13:54:14 2015
> @@ -35,7 +35,7 @@ protected:
>    ObjectFile<ELFT> *File;
>  
>  public:
> -  enum Kind { Regular, Merge };
> +  enum Kind { Regular, EHFrame, Merge };
>    Kind SectionKind;
>  
>    InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
> @@ -78,8 +78,7 @@ public:
>    template <bool isRela>
>    void relocate(uint8_t *Buf, uint8_t *BufEnd,
>                  llvm::iterator_range<
> -                    const llvm::object::Elf_Rel_Impl<ELFT, isRela>
> *> Rels,
> -                uintX_t BaseAddr);
> +                    const llvm::object::Elf_Rel_Impl<ELFT, isRela>
> *> Rels);
>  };
>  
>  template <class ELFT>
> @@ -87,15 +86,25 @@ InputSectionBase<ELFT>
>      InputSectionBase<ELFT>::Discarded(nullptr, nullptr,
>                                        InputSectionBase<ELFT>::Regular);
>  
> +template <class ELFT> class SplitInputSection : public
> InputSectionBase<ELFT> {
> +  typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
> +  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
> +
> +public:
> +  SplitInputSection(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
> +                    typename InputSectionBase<ELFT>::Kind
> SectionKind);
> +  std::vector<std::pair<uintX_t, uintX_t>> Offsets;
> +  std::pair<std::pair<uintX_t, uintX_t> *, uintX_t>
> +  getRangeAndSize(uintX_t Offset);
> +};
> +
>  // This corresponds to a SHF_MERGE section of an input file.
> -template <class ELFT> class MergeInputSection : public
> InputSectionBase<ELFT> {
> -  typedef InputSectionBase<ELFT> Base;
> +template <class ELFT> class MergeInputSection : public
> SplitInputSection<ELFT> {
>    typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
>    typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
>    typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
>  
>  public:
> -  std::vector<std::pair<uintX_t, uintX_t>> Offsets;
>    MergeInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
>    static bool classof(const InputSectionBase<ELFT> *S);
>    // Translate an offset in the input section to an offset in the
>    output
> @@ -103,6 +112,22 @@ public:
>    uintX_t getOffset(uintX_t Offset);
>  };
>  
> +// This corresponds to a .eh_frame section of an input file.
> +template <class ELFT> class EHInputSection : public
> SplitInputSection<ELFT> {
> +public:
> +  typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
> +  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
> +  EHInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
> +  static bool classof(const InputSectionBase<ELFT> *S);
> +
> +  // Translate an offset in the input section to an offset in the
> output
> +  // section.
> +  uintX_t getOffset(uintX_t Offset);
> +
> +  // Relocation section that refer to this one.
> +  const Elf_Shdr *RelocSection = nullptr;
> +};
> +
>  // This corresponds to a non SHF_MERGE section of an input file.
>  template <class ELFT> class InputSection : public
>  InputSectionBase<ELFT> {
>    typedef InputSectionBase<ELFT> Base;
> 
> Modified: lld/trunk/ELF/OutputSections.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=252790&r1=252789&r2=252790&view=diff
> ==============================================================================
> --- lld/trunk/ELF/OutputSections.cpp (original)
> +++ lld/trunk/ELF/OutputSections.cpp Wed Nov 11 13:54:14 2015
> @@ -176,7 +176,7 @@ template <class ELFT> void RelocationSec
>      auto *P = reinterpret_cast<Elf_Rel *>(Buf);
>      Buf += EntrySize;
>  
> -    const InputSection<ELFT> &C = Rel.C;
> +    InputSectionBase<ELFT> &C = Rel.C;
>      const Elf_Rel &RI = Rel.RI;
>      uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
>      const ObjectFile<ELFT> &File = *C.getFile();
> @@ -223,7 +223,7 @@ template <class ELFT> void RelocationSec
>        P->r_offset = Out<ELFT>::Bss->getVA() +
>                      dyn_cast<SharedSymbol<ELFT>>(Body)->OffsetInBSS;
>      } else {
> -      P->r_offset = RI.r_offset + C.OutSec->getVA() + C.OutSecOff;
> +      P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA();
>      }
>  
>      uintX_t OrigAddend = 0;
> @@ -789,6 +789,150 @@ template <class ELFT> void OutputSection
>  }
>  
>  template <class ELFT>
> +EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t
> sh_type,
> +                                       uintX_t sh_flags)
> +    : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
> +
> +template <class ELFT>
> +EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index)
> +    : S(S), Index(Index) {}
> +
> +template <class ELFT> StringRef EHRegion<ELFT>::data() const {
> +  ArrayRef<uint8_t> SecData = S->getSectionData();
> +  ArrayRef<std::pair<uintX_t, uintX_t>> Offsets = S->Offsets;
> +  size_t Start = Offsets[Index].first;
> +  size_t End =
> +      Index == Offsets.size() - 1 ? SecData.size() : Offsets[Index +
> 1].first;
> +  return StringRef((const char *)SecData.data() + Start, End -
> Start);
> +}
> +
> +template <class ELFT>
> +Cie<ELFT>::Cie(EHInputSection<ELFT> *S, unsigned Index)
> +    : EHRegion<ELFT>(S, Index) {}
> +
> +template <class ELFT>
> +template <bool IsRela>
> +void EHOutputSection<ELFT>::addSectionAux(
> +    EHInputSection<ELFT> *S,
> +    iterator_range<const Elf_Rel_Impl<ELFT, IsRela> *> Rels) {
> +  const endianness E = ELFT::TargetEndianness;
> +
> +  S->OutSec = this;
> +  uint32_t Align = S->getAlign();
> +  if (Align > this->Header.sh_addralign)
> +    this->Header.sh_addralign = Align;
> +
> +  Sections.push_back(S);
> +
> +  ArrayRef<uint8_t> SecData = S->getSectionData();
> +  ArrayRef<uint8_t> D = SecData;
> +  uintX_t Offset = 0;
> +  auto RelI = Rels.begin();
> +  auto RelE = Rels.end();
> +
> +  DenseMap<unsigned, unsigned> OffsetToIndex;
> +  while (!D.empty()) {
> +    if (D.size() < 4)
> +      error("Truncated CIE/FDE length");
> +    uint32_t Length = read32<E>(D.data());
> +    Length += 4;
> +
> +    unsigned Index = S->Offsets.size();
> +    S->Offsets.push_back(std::make_pair(Offset, -1));
> +
> +    if (Length > D.size())
> +      error("CIE/FIE ends past the end of the section");
> +    StringRef Entry((const char *)D.data(), Length);
> +
> +    while (RelI != RelE && RelI->r_offset < Offset)
> +      ++RelI;
> +    uintX_t NextOffset = Offset + Length;
> +    bool HasReloc = RelI != RelE && RelI->r_offset < NextOffset;
> +
> +    uint32_t ID = read32<E>(D.data() + 4);
> +    if (ID == 0) {
> +      // CIE
> +      Cie<ELFT> C(S, Index);
> +
> +      StringRef Personality;
> +      if (HasReloc) {
> +        uint32_t SymIndex = RelI->getSymbol(Config->Mips64EL);
> +        SymbolBody &Body =
> *S->getFile()->getSymbolBody(SymIndex)->repl();
> +        Personality = Body.getName();
> +      }
> +
> +      std::pair<StringRef, StringRef> CieInfo(Entry, Personality);
> +      auto P = CieMap.insert(std::make_pair(CieInfo, Cies.size()));
> +      if (P.second) {
> +        Cies.push_back(C);
> +        this->Header.sh_size += Length;
> +      }
> +      OffsetToIndex[Offset] = P.first->second;
> +    } else {
> +      if (!HasReloc)
> +        error("FDE doesn't reference another section");
> +      InputSectionBase<ELFT> *Target = S->getRelocTarget(*RelI);
> +      if (Target != &InputSection<ELFT>::Discarded &&
> Target->isLive()) {
> +        uint32_t CieOffset = Offset + 4 - ID;
> +        auto I = OffsetToIndex.find(CieOffset);
> +        if (I == OffsetToIndex.end())
> +          error("Invalid CIE reference");
> +        Cies[I->second].Fdes.push_back(EHRegion<ELFT>(S, Index));
> +        this->Header.sh_size += Length;
> +      }
> +    }
> +
> +    Offset = NextOffset;
> +    D = D.slice(Length);
> +  }
> +}
> +
> +template <class ELFT>
> +void EHOutputSection<ELFT>::addSection(EHInputSection<ELFT> *S) {
> +  const Elf_Shdr *RelSec = S->RelocSection;
> +  if (!RelSec)
> +    return addSectionAux(
> +        S, make_range((const Elf_Rela *)nullptr, (const Elf_Rela
> *)nullptr));
> +  ELFFile<ELFT> &Obj = S->getFile()->getObj();
> +  if (RelSec->sh_type == SHT_RELA)
> +    return addSectionAux(S, Obj.relas(RelSec));
> +  return addSectionAux(S, Obj.rels(RelSec));
> +}
> +
> +template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t
> *Buf) {
> +  const endianness E = ELFT::TargetEndianness;
> +  size_t Offset = 0;
> +  for (const Cie<ELFT> &C : Cies) {
> +    size_t CieOffset = Offset;
> +
> +    StringRef CieData = C.data();
> +    memcpy(Buf + Offset, CieData.data(), CieData.size());
> +    C.S->Offsets[C.Index].second = Offset;
> +    Offset += CieData.size();
> +
> +    for (const EHRegion<ELFT> &F : C.Fdes) {
> +      StringRef FdeData = F.data();
> +      memcpy(Buf + Offset, FdeData.data(), 4);              //
> Legnth
> +      write32<E>(Buf + Offset + 4, Offset + 4 - CieOffset); //
> Pointer
> +      memcpy(Buf + Offset + 8, FdeData.data() + 8, FdeData.size() -
> 8);
> +      F.S->Offsets[F.Index].second = Offset;
> +      Offset += FdeData.size();
> +    }
> +  }
> +
> +  for (EHInputSection<ELFT> *S : Sections) {
> +    const Elf_Shdr *RelSec = S->RelocSection;
> +    if (!RelSec)
> +      continue;
> +    ELFFile<ELFT> &EObj = S->getFile()->getObj();
> +    if (RelSec->sh_type == SHT_RELA)
> +      S->relocate(Buf, nullptr, EObj.relas(RelSec));
> +    else
> +      S->relocate(Buf, nullptr, EObj.relas(RelSec));
> +  }
> +}
> +
> +template <class ELFT>
>  MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name,
>  uint32_t sh_type,
>                                               uintX_t sh_flags)
>      : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
> @@ -1141,6 +1285,11 @@ template class OutputSection<ELF32BE>;
>  template class OutputSection<ELF64LE>;
>  template class OutputSection<ELF64BE>;
>  
> +template class EHOutputSection<ELF32LE>;
> +template class EHOutputSection<ELF32BE>;
> +template class EHOutputSection<ELF64LE>;
> +template class EHOutputSection<ELF64BE>;
> +
>  template class MergeOutputSection<ELF32LE>;
>  template class MergeOutputSection<ELF32BE>;
>  template class MergeOutputSection<ELF64LE>;
> 
> Modified: lld/trunk/ELF/OutputSections.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=252790&r1=252789&r2=252790&view=diff
> ==============================================================================
> --- lld/trunk/ELF/OutputSections.h (original)
> +++ lld/trunk/ELF/OutputSections.h Wed Nov 11 13:54:14 2015
> @@ -27,7 +27,9 @@ class SymbolBody;
>  template <class ELFT> class SymbolTable;
>  template <class ELFT> class SymbolTableSection;
>  template <class ELFT> class StringTableSection;
> +template <class ELFT> class EHInputSection;
>  template <class ELFT> class InputSection;
> +template <class ELFT> class InputSectionBase;
>  template <class ELFT> class MergeInputSection;
>  template <class ELFT> class OutputSection;
>  template <class ELFT> class ObjectFile;
> @@ -158,7 +160,7 @@ private:
>  
>  template <class ELFT> struct DynamicReloc {
>    typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
> -  InputSection<ELFT> &C;
> +  InputSectionBase<ELFT> &C;
>    const Elf_Rel &RI;
>  };
>  
> @@ -246,6 +248,46 @@ private:
>    llvm::StringTableBuilder Builder{llvm::StringTableBuilder::RAW};
>  };
>  
> +// FDE or CIE
> +template <class ELFT> struct EHRegion {
> +  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
> +  EHRegion(EHInputSection<ELFT> *S, unsigned Index);
> +  StringRef data() const;
> +  EHInputSection<ELFT> *S;
> +  unsigned Index;
> +};
> +
> +template <class ELFT> struct Cie : public EHRegion<ELFT> {
> +  Cie(EHInputSection<ELFT> *S, unsigned Index);
> +  std::vector<EHRegion<ELFT>> Fdes;
> +};
> +
> +template <class ELFT>
> +class EHOutputSection final : public OutputSectionBase<ELFT> {
> +public:
> +  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
> +  typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
> +  typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
> +  typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
> +  EHOutputSection(StringRef Name, uint32_t sh_type, uintX_t
> sh_flags);
> +  void writeTo(uint8_t *Buf) override;
> +
> +  template <bool IsRela>
> +  void addSectionAux(
> +      EHInputSection<ELFT> *S,
> +      llvm::iterator_range<const llvm::object::Elf_Rel_Impl<ELFT,
> IsRela> *>
> +          Rels);
> +
> +  void addSection(EHInputSection<ELFT> *S);
> +
> +private:
> +  std::vector<EHInputSection<ELFT> *> Sections;
> +  std::vector<Cie<ELFT>> Cies;
> +
> +  // Maps CIE content + personality to a index in Cies.
> +  llvm::DenseMap<std::pair<StringRef, StringRef>, unsigned> CieMap;
> +};
> +
>  template <class ELFT>
>  class InterpSection final : public OutputSectionBase<ELFT> {
>  public:
> 
> Modified: lld/trunk/ELF/Writer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=252790&r1=252789&r2=252790&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Wed Nov 11 13:54:14 2015
> @@ -42,9 +42,10 @@ private:
>    void copyLocalSymbols();
>    void createSections();
>    template <bool isRela>
> -  void scanRelocs(InputSection<ELFT> &C,
> +  void scanRelocs(InputSectionBase<ELFT> &C,
>                    iterator_range<const Elf_Rel_Impl<ELFT, isRela> *>
>                    Rels);
>    void scanRelocs(InputSection<ELFT> &C);
> +  void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr
> &RelSec);
>    void assignAddresses();
>    void openFile(StringRef OutputPath);
>    void writeHeader();
> @@ -66,6 +67,7 @@ private:
>  
>    SpecificBumpPtrAllocator<OutputSection<ELFT>> SecAlloc;
>    SpecificBumpPtrAllocator<MergeOutputSection<ELFT>> MSecAlloc;
> +  SpecificBumpPtrAllocator<EHOutputSection<ELFT>> EHSecAlloc;
>    BumpPtrAllocator Alloc;
>    std::vector<OutputSectionBase<ELFT> *> OutputSections;
>    unsigned getNumSections() const { return OutputSections.size() +
>    1; }
> @@ -181,7 +183,7 @@ template <bool Is64Bits> struct DenseMap
>  template <class ELFT>
>  template <bool isRela>
>  void Writer<ELFT>::scanRelocs(
> -    InputSection<ELFT> &C,
> +    InputSectionBase<ELFT> &C,
>      iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
>    typedef Elf_Rel_Impl<ELFT, isRela> RelType;
>    const ObjectFile<ELFT> &File = *C.getFile();
> @@ -255,18 +257,21 @@ void Writer<ELFT>::scanRelocs(
>  }
>  
>  template <class ELFT> void
>  Writer<ELFT>::scanRelocs(InputSection<ELFT> &C) {
> -  ObjectFile<ELFT> *File = C.getFile();
> -  ELFFile<ELFT> &EObj = File->getObj();
> -
>    if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
>      return;
>  
> -  for (const Elf_Shdr *RelSec : C.RelocSections) {
> -    if (RelSec->sh_type == SHT_RELA)
> -      scanRelocs(C, EObj.relas(RelSec));
> -    else
> -      scanRelocs(C, EObj.rels(RelSec));
> -  }
> +  for (const Elf_Shdr *RelSec : C.RelocSections)
> +    scanRelocs(C, *RelSec);
> +}
> +
> +template <class ELFT>
> +void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S,
> +                              const Elf_Shdr &RelSec) {
> +  ELFFile<ELFT> &EObj = S.getFile()->getObj();
> +  if (RelSec.sh_type == SHT_RELA)
> +    scanRelocs(S, EObj.relas(&RelSec));
> +  else
> +    scanRelocs(S, EObj.rels(&RelSec));
>  }
>  
>  template <class ELFT>
> @@ -487,8 +492,8 @@ template <class ELFT> void Writer<ELFT>:
>        // For SHF_MERGE we create different output sections for each
>        sh_entsize.
>        // This makes each output section simple and keeps a single
>        level
>        // mapping from input to output.
> -      auto *IS = dyn_cast<InputSection<ELFT>>(C);
> -      uintX_t EntSize = IS ? 0 : H->sh_entsize;
> +      typename InputSectionBase<ELFT>::Kind K = C->SectionKind;
> +      uintX_t EntSize = K != InputSectionBase<ELFT>::Merge ? 0 :
> H->sh_entsize;
>        uint32_t OutType = H->sh_type;
>        if (OutType == SHT_PROGBITS && C->getSectionName() ==
>        ".eh_frame" &&
>            Config->EMachine == EM_X86_64)
> @@ -497,20 +502,37 @@ template <class ELFT> void Writer<ELFT>:
>                                       OutType, OutFlags, EntSize};
>        OutputSectionBase<ELFT> *&Sec = Map[Key];
>        if (!Sec) {
> -        if (IS)
> +        switch (K) {
> +        case InputSectionBase<ELFT>::Regular:
>            Sec = new (SecAlloc.Allocate())
>                OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
> -        else
> +          break;
> +        case InputSectionBase<ELFT>::EHFrame:
> +          Sec = new (EHSecAlloc.Allocate())
> +              EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
> +          break;
> +        case InputSectionBase<ELFT>::Merge:
>            Sec = new (MSecAlloc.Allocate())
>                MergeOutputSection<ELFT>(Key.Name, Key.Type,
>                Key.Flags);
> +          break;
> +        }
>          OutputSections.push_back(Sec);
>          RegularSections.push_back(Sec);
>        }
> -      if (IS)
> -        static_cast<OutputSection<ELFT> *>(Sec)->addSection(IS);
> -      else
> +      switch (K) {
> +      case InputSectionBase<ELFT>::Regular:
> +        static_cast<OutputSection<ELFT> *>(Sec)
> +            ->addSection(cast<InputSection<ELFT>>(C));
> +        break;
> +      case InputSectionBase<ELFT>::EHFrame:
> +        static_cast<EHOutputSection<ELFT> *>(Sec)
> +            ->addSection(cast<EHInputSection<ELFT>>(C));
> +        break;
> +      case InputSectionBase<ELFT>::Merge:
>          static_cast<MergeOutputSection<ELFT> *>(Sec)
>              ->addSection(cast<MergeInputSection<ELFT>>(C));
> +        break;
> +      }
>      }
>    }
>  
> @@ -554,11 +576,17 @@ template <class ELFT> void Writer<ELFT>:
>  
>    // Scan relocations. This must be done after every symbol is
>    declared so that
>    // we can correctly decide if a dynamic relocation is needed.
> -  for (const std::unique_ptr<ObjectFile<ELFT>> &F :
> Symtab.getObjectFiles())
> -    for (InputSectionBase<ELFT> *B : F->getSections())
> -      if (auto *S = dyn_cast_or_null<InputSection<ELFT>>(B))
> +  for (const std::unique_ptr<ObjectFile<ELFT>> &F :
> Symtab.getObjectFiles()) {
> +    for (InputSectionBase<ELFT> *B : F->getSections()) {
> +      if (auto *S = dyn_cast_or_null<InputSection<ELFT>>(B)) {
>          if (S != &InputSection<ELFT>::Discarded && S->isLive())
>            scanRelocs(*S);
> +      } else if (auto *S =
> dyn_cast_or_null<EHInputSection<ELFT>>(B)) {
> +        if (S->RelocSection)
> +          scanRelocs(*S, *S->RelocSection);
> +      }
> +    }
> +  }
>  
>    std::vector<DefinedCommon<ELFT> *> CommonSymbols;
>    std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
> 
> Added: lld/trunk/test/elf2/Inputs/invalid-multiple-eh-relocs.elf
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/invalid-multiple-eh-relocs.elf?rev=252790&view=auto
> ==============================================================================
> Binary files
> lld/trunk/test/elf2/Inputs/invalid-multiple-eh-relocs.elf (added)
> and lld/trunk/test/elf2/Inputs/invalid-multiple-eh-relocs.elf Wed
> Nov 11 13:54:14 2015 differ
> 
> Added: lld/trunk/test/elf2/eh-frame-merge.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/eh-frame-merge.s?rev=252790&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/eh-frame-merge.s (added)
> +++ lld/trunk/test/elf2/eh-frame-merge.s Wed Nov 11 13:54:14 2015
> @@ -0,0 +1,58 @@
> +// REQUIRES: x86
> +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
> +// RUN: ld.lld2 %t.o %t.o -o %t -shared
> +// RUN: llvm-readobj -s -section-data %t | FileCheck %s
> +
> +        .section	foo,"ax", at progbits
> +	.cfi_startproc
> +        nop
> +	.cfi_endproc
> +
> +        .section	bar,"axG", at progbits,foo,comdat
> +        .cfi_startproc
> +        nop
> +        nop
> +	.cfi_endproc
> +
> +// FIXME: We could really use a .eh_frame parser.
> +// The intention is to show that:
> +// * There is only one copy of the CIE
> +// * There are two copies of the first FDE
> +// * There is only one copy of the second FDE
> +
> +// CHECK:      Name: .eh_frame
> +// CHECK-NEXT: Type: SHT_X86_64_UNWIND
> +// CHECK-NEXT: Flags [
> +// CHECK-NEXT:   SHF_ALLOC
> +// CHECK-NEXT: ]
> +// CHECK-NEXT: Address:
> +// CHECK-NEXT: Offset:
> +// CHECK-NEXT: Size:
> +// CHECK-NEXT: Link: 0
> +// CHECK-NEXT: Info: 0
> +// CHECK-NEXT: AddressAlignment: 8
> +// CHECK-NEXT: EntrySize: 0
> +// CHECK-NEXT: SectionData (
> +// CHECK-NEXT:   0000: 14000000 00000000 017A5200 01781001  |
> +// CHECK-NEXT:   0010: 1B0C0708 90010000 10000000 1C000000  |
> +// CHECK-NEXT:   0020: 880E0000 01000000 00000000 10000000  |
> +// CHECK-NEXT:   0030: 30000000 760E0000 02000000 00000000  |
> +// CHECK-NEXT:   0040: 10000000 44000000 610E0000 01000000  |
> +// CHECK-NEXT:   0050: 00000000                             |
> +// CHECK-NEXT: )
> +
> +// CHECK:      Name: foo
> +// CHECK-NEXT: Type: SHT_PROGBITS
> +// CHECK-NEXT: Flags [
> +// CHECK-NEXT:   SHF_ALLOC
> +// CHECK-NEXT:   SHF_EXECINSTR
> +// CHECK-NEXT: ]
> +// CHECK-NEXT: Address: 0x1000
> +
> +// CHECK:      Name: bar
> +// CHECK-NEXT: Type: SHT_PROGBITS
> +// CHECK-NEXT: Flags [
> +// CHECK-NEXT:   SHF_ALLOC
> +// CHECK-NEXT:   SHF_EXECINSTR
> +// CHECK-NEXT: ]
> +// CHECK-NEXT: Address: 0x1002
> 
> Added: lld/trunk/test/elf2/eh-frame-plt.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/eh-frame-plt.s?rev=252790&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/eh-frame-plt.s (added)
> +++ lld/trunk/test/elf2/eh-frame-plt.s Wed Nov 11 13:54:14 2015
> @@ -0,0 +1,16 @@
> +// REQUIRES: x86
> +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux
> %p/Inputs/shared.s -o %t.o
> +// RUN: ld.lld2 %t.o -o %t.so -shared
> +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
> +// RUN: ld.lld2 %t2.o %t.so -o %t
> +// RUN: llvm-readobj -r %t | FileCheck %s
> +
> +	.globl	_start
> +_start:
> +	.cfi_startproc
> +	.cfi_personality 3, bar
> +	.cfi_endproc
> +
> +// CHECK:      Section ({{.*}}) .rela.plt {
> +// CHECK-NEXT:   R_X86_64_JUMP_SLOT bar 0x0
> +// CHECK-NEXT: }
> 
> Added: lld/trunk/test/elf2/invalid-cie-length.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/invalid-cie-length.s?rev=252790&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/invalid-cie-length.s (added)
> +++ lld/trunk/test/elf2/invalid-cie-length.s Wed Nov 11 13:54:14 2015
> @@ -0,0 +1,9 @@
> +// REQUIRES: x86
> +
> +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
> +// RUN: not ld.lld2 %t -o %t2 2>&1 | FileCheck %s
> +
> +        .section .eh_frame
> +        .byte 0
> +
> +// CHECK: Truncated CIE/FDE length
> 
> Added: lld/trunk/test/elf2/invalid-cie-length2.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/invalid-cie-length2.s?rev=252790&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/invalid-cie-length2.s (added)
> +++ lld/trunk/test/elf2/invalid-cie-length2.s Wed Nov 11 13:54:14
> 2015
> @@ -0,0 +1,9 @@
> +// REQUIRES: x86
> +
> +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
> +// RUN: not ld.lld2 %t -o %t2 2>&1 | FileCheck %s
> +
> +        .section .eh_frame
> +        .long 42
> +
> +// CHECK: CIE/FIE ends past the end of the section
> 
> Added: lld/trunk/test/elf2/invalid-cie-reference.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/invalid-cie-reference.s?rev=252790&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/invalid-cie-reference.s (added)
> +++ lld/trunk/test/elf2/invalid-cie-reference.s Wed Nov 11 13:54:14
> 2015
> @@ -0,0 +1,32 @@
> +// REQUIRES: x86
> +
> +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
> +// RUN: not ld.lld2 %t -o %t2 2>&1 | FileCheck %s
> +
> +        .section .eh_frame
> +        .long 0x14
> +        .long 0x0
> +        .byte 0x01
> +        .byte 0x7a
> +        .byte 0x52
> +        .byte 0x00
> +        .byte 0x01
> +        .byte 0x78
> +        .byte 0x10
> +        .byte 0x01
> +        .byte 0x1b
> +        .byte 0x0c
> +        .byte 0x07
> +        .byte 0x08
> +        .byte 0x90
> +        .byte 0x01
> +        .short 0x0
> +
> +        .long 0x14
> +        .long 0x1b
> +        .long .text
> +        .long 0x0
> +        .long 0x0
> +        .long 0x0
> +
> +// CHECK: Invalid CIE reference
> 
> Modified: lld/trunk/test/elf2/invalid-elf.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/invalid-elf.test?rev=252790&r1=252789&r2=252790&view=diff
> ==============================================================================
> --- lld/trunk/test/elf2/invalid-elf.test (original)
> +++ lld/trunk/test/elf2/invalid-elf.test Wed Nov 11 13:54:14 2015
> @@ -27,4 +27,8 @@
>  # RUN:   FileCheck --check-prefix=INVALID-SHENTSIZE-ZERO %s
>  # INVALID-SHENTSIZE-ZERO: SHF_MERGE section size must be a multiple
>  of sh_entsize
>  
> +# RUN: not ld.lld2 %p/Inputs/invalid-multiple-eh-relocs.elf -o %t2
> 2>&1 | \
> +# RUN:   FileCheck --check-prefix=INVALID-EH-RELOCS %s
> +# INVALID-EH-RELOCS: Multiple relocation sections to .eh_frame are
> not supported
> +
>  .long foo
> 
> Added: lld/trunk/test/elf2/invalid-fde-rel.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/invalid-fde-rel.s?rev=252790&view=auto
> ==============================================================================
> --- lld/trunk/test/elf2/invalid-fde-rel.s (added)
> +++ lld/trunk/test/elf2/invalid-fde-rel.s Wed Nov 11 13:54:14 2015
> @@ -0,0 +1,32 @@
> +// REQUIRES: x86
> +
> +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
> +// RUN: not ld.lld2 %t -o %t2 2>&1 | FileCheck %s
> +
> +        .section .eh_frame
> +        .long 0x14
> +        .long 0x0
> +        .byte 0x01
> +        .byte 0x7a
> +        .byte 0x52
> +        .byte 0x00
> +        .byte 0x01
> +        .byte 0x78
> +        .byte 0x10
> +        .byte 0x01
> +        .byte 0x1b
> +        .byte 0x0c
> +        .byte 0x07
> +        .byte 0x08
> +        .byte 0x90
> +        .byte 0x01
> +        .short 0x0
> +
> +        .long 0x14
> +        .long 0x1c
> +        .long 0x0
> +        .long 0x0
> +        .long 0x0
> +        .long 0x0
> +
> +// CHECK: FDE doesn't reference another section
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory


More information about the llvm-commits mailing list