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