[lld] r252790 - Add support for processing .eh_frame.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 5 17:11:23 PST 2016
This is a bit old commit, but I have a question.
On Wed, Nov 11, 2015 at 11:54 AM, Rafael Espindola via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> 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);
>
So, here, CIEs are uniquified by their contents and some symbol names. What
is the actual rule? I want to know what it is intended to do for what.
> + 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160205/23802ab2/attachment.html>
More information about the llvm-commits
mailing list