[lld] r252790 - Add support for processing .eh_frame.
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 11 17:54:16 PST 2016
On Fri, Nov 27, 2015 at 12:22 PM, Hal Finkel via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Hi Rafael,
>
> You had suggested that I model proper PPC64 .opd support after this implementation; could you please elaborate?
>
+1, I hit the same issue on PPC.
Thanks!
> 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
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
--
Davide
"There are no solved problems; there are only problems that are more
or less solved" -- Henri Poincare
More information about the llvm-commits
mailing list