[lld] r265673 - Don't create dynamic relocs for discarded .eh_frame entries.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 7 07:22:09 PDT 2016
Author: rafael
Date: Thu Apr 7 09:22:09 2016
New Revision: 265673
URL: http://llvm.org/viewvc/llvm-project?rev=265673&view=rev
Log:
Don't create dynamic relocs for discarded .eh_frame entries.
This requires knowing input section offsets in output sections before
scanRelocs. This is generally a good thing and should allow further
simplifications in the creation of dynamic relocations.
Added:
lld/trunk/test/ELF/eh-frame-dyn-rel.s
Modified:
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=265673&r1=265672&r2=265673&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Apr 7 09:22:09 2016
@@ -307,7 +307,7 @@ typename ELFT::uint DynamicReloc<ELFT>::
case Off_LTlsIndex:
return Out<ELFT>::Got->getTlsIndexVA();
case Off_Sec:
- return OffsetSec->getOffset(OffsetInSec) + OffsetSec->OutSec->getVA();
+ return OffsetInSec + OffsetSec->getVA();
case Off_Bss:
return cast<SharedSymbol<ELFT>>(Sym)->OffsetInBss + Out<ELFT>::Bss->getVA();
case Off_Got:
@@ -836,16 +836,11 @@ static int getPriority(StringRef S) {
return V;
}
-// This function is called after we sort input sections
-// and scan relocations to setup sections' offsets.
-template <class ELFT> void OutputSection<ELFT>::assignOffsets() {
- uintX_t Off = this->Header.sh_size;
- for (InputSection<ELFT> *S : Sections) {
- Off = alignTo(Off, S->Align);
- S->OutSecOff = Off;
- Off += S->getSize();
- }
- this->Header.sh_size = Off;
+template <class ELFT>
+void OutputSection<ELFT>::forEachInputSection(
+ std::function<void(InputSectionBase<ELFT> *S)> F) {
+ for (InputSection<ELFT> *S : Sections)
+ F(S);
}
// Sorts input sections by section name suffixes, so that .foo.N comes
@@ -956,6 +951,13 @@ EHOutputSection<ELFT>::EHOutputSection(S
}
template <class ELFT>
+void EHOutputSection<ELFT>::forEachInputSection(
+ std::function<void(InputSectionBase<ELFT> *)> F) {
+ for (EHInputSection<ELFT> *S : Sections)
+ F(S);
+}
+
+template <class ELFT>
EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index)
: S(S), Index(Index) {}
@@ -1186,31 +1188,43 @@ void EHOutputSection<ELFT>::addSection(I
}
template <class ELFT>
-static typename ELFT::uint writeAlignedCieOrFde(StringRef Data, uint8_t *Buf) {
+static void writeAlignedCieOrFde(StringRef Data, uint8_t *Buf) {
typedef typename ELFT::uint uintX_t;
const endianness E = ELFT::TargetEndianness;
uint64_t Len = alignTo(Data.size(), sizeof(uintX_t));
write32<E>(Buf, Len - 4);
memcpy(Buf + 4, Data.data() + 4, Data.size() - 4);
- return Len;
}
-template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) {
- const endianness E = ELFT::TargetEndianness;
+template <class ELFT> void EHOutputSection<ELFT>::finalize() {
+ if (Finalized)
+ return;
+ Finalized = true;
+
size_t Offset = 0;
for (const Cie<ELFT> &C : Cies) {
- size_t CieOffset = Offset;
-
- uintX_t CIELen = writeAlignedCieOrFde<ELFT>(C.data(), Buf + Offset);
C.S->Offsets[C.Index].second = Offset;
- Offset += CIELen;
+ Offset += alignTo(C.data().size(), sizeof(uintX_t));
for (const EHRegion<ELFT> &F : C.Fdes) {
- uintX_t Len = writeAlignedCieOrFde<ELFT>(F.data(), Buf + Offset);
- write32<E>(Buf + Offset + 4, Offset + 4 - CieOffset); // Pointer
F.S->Offsets[F.Index].second = Offset;
+ Offset += alignTo(F.data().size(), sizeof(uintX_t));
+ }
+ }
+}
+
+template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) {
+ const endianness E = ELFT::TargetEndianness;
+ for (const Cie<ELFT> &C : Cies) {
+ size_t CieOffset = C.S->Offsets[C.Index].second;
+ writeAlignedCieOrFde<ELFT>(C.data(), Buf + CieOffset);
+
+ for (const EHRegion<ELFT> &F : C.Fdes) {
+ size_t Offset = F.S->Offsets[F.Index].second;
+ writeAlignedCieOrFde<ELFT>(F.data(), Buf + Offset);
+ write32<E>(Buf + Offset + 4, Offset + 4 - CieOffset); // Pointer
+
Out<ELFT>::EhFrameHdr->addFde(C.FdeEncoding, Offset, Buf + Offset + 8);
- Offset += Len;
}
}
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=265673&r1=265672&r2=265673&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Thu Apr 7 09:22:09 2016
@@ -87,8 +87,9 @@ public:
// Typically the first section of each PT_LOAD segment has this flag.
bool PageAlign = false;
- virtual void assignOffsets() {}
virtual void finalize() {}
+ virtual void
+ forEachInputSection(std::function<void(InputSectionBase<ELFT> *)> F) {}
virtual void writeTo(uint8_t *Buf) {}
virtual ~OutputSectionBase() = default;
@@ -183,7 +184,7 @@ template <class ELFT> struct DynamicRelo
} OKind;
SymbolBody *Sym = nullptr;
- InputSectionBase<ELFT> *OffsetSec = nullptr;
+ OutputSectionBase<ELFT> *OffsetSec = nullptr;
uintX_t OffsetInSec = 0;
bool UseSymVA = false;
uintX_t Addend = 0;
@@ -194,7 +195,7 @@ template <class ELFT> struct DynamicRelo
DynamicReloc(uint32_t Type, OffsetKind OKind, bool UseSymVA, SymbolBody *Sym)
: Type(Type), OKind(OKind), Sym(Sym), UseSymVA(UseSymVA) {}
- DynamicReloc(uint32_t Type, InputSectionBase<ELFT> *OffsetSec,
+ DynamicReloc(uint32_t Type, OutputSectionBase<ELFT> *OffsetSec,
uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym,
uintX_t Addend)
: Type(Type), OKind(Off_Sec), Sym(Sym), OffsetSec(OffsetSec),
@@ -272,10 +273,9 @@ public:
void sortInitFini();
void sortCtorsDtors();
void writeTo(uint8_t *Buf) override;
- void assignOffsets() override;
void finalize() override;
-
-private:
+ void
+ forEachInputSection(std::function<void(InputSectionBase<ELFT> *)> F) override;
std::vector<InputSection<ELFT> *> Sections;
};
@@ -321,6 +321,9 @@ public:
typedef typename ELFT::Rela Elf_Rela;
EHOutputSection(StringRef Name, uint32_t Type, uintX_t Flags);
void writeTo(uint8_t *Buf) override;
+ void finalize() override;
+ void
+ forEachInputSection(std::function<void(InputSectionBase<ELFT> *)> F) override;
template <class RelTy>
void addSectionAux(EHInputSection<ELFT> *S, llvm::ArrayRef<RelTy> Rels);
@@ -335,6 +338,7 @@ private:
// Maps CIE content + personality to a index in Cies.
llvm::DenseMap<std::pair<StringRef, SymbolBody *>, unsigned> CieMap;
+ bool Finalized = false;
};
template <class ELFT>
@@ -493,6 +497,8 @@ public:
bool Live = false;
+ EHOutputSection<ELFT> *Sec = nullptr;
+
private:
struct FdeData {
uint8_t Enc;
@@ -502,7 +508,6 @@ private:
uintX_t getFdePc(uintX_t EhVA, const FdeData &F);
- EHOutputSection<ELFT> *Sec = nullptr;
std::vector<FdeData> FdeList;
};
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=265673&r1=265672&r2=265673&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Apr 7 09:22:09 2016
@@ -349,6 +349,10 @@ void Writer<ELFT>::scanRelocs(InputSecti
if (Target->isHintRel(Type))
continue;
+ uintX_t Offset = C.getOffset(RI.r_offset);
+ if (Offset == (uintX_t)-1)
+ continue;
+
if (Target->isGotRelative(Type))
HasGotOffRel = true;
@@ -364,7 +368,7 @@ void Writer<ELFT>::scanRelocs(InputSecti
}
if (Target->needsDynRelative(Type))
- Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, true,
+ Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, C.OutSec, Offset, true,
&Body, getAddend<ELFT>(RI)});
// If a symbol in a DSO is referenced directly instead of through GOT,
@@ -447,7 +451,7 @@ void Writer<ELFT>::scanRelocs(InputSecti
if (Preemptible) {
// We don't know anything about the finaly symbol. Just ask the dynamic
// linker to handle the relocation for us.
- Out<ELFT>::RelaDyn->addReloc({Target->getDynRel(Type), &C, RI.r_offset,
+ Out<ELFT>::RelaDyn->addReloc({Target->getDynRel(Type), C.OutSec, Offset,
false, &Body, getAddend<ELFT>(RI)});
continue;
}
@@ -464,13 +468,13 @@ void Writer<ELFT>::scanRelocs(InputSecti
uintX_t Addend = getAddend<ELFT>(RI);
if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC) {
- Out<ELFT>::RelaDyn->addReloc({R_PPC64_RELATIVE, &C, RI.r_offset, false,
+ Out<ELFT>::RelaDyn->addReloc({R_PPC64_RELATIVE, C.OutSec, Offset, false,
nullptr,
(uintX_t)getPPC64TocBase() + Addend});
continue;
}
Out<ELFT>::RelaDyn->addReloc(
- {Target->RelativeRel, &C, RI.r_offset, true, &Body, Addend});
+ {Target->RelativeRel, C.OutSec, Offset, true, &Body, Addend});
}
// Scan relocations for necessary thunks.
@@ -1046,24 +1050,29 @@ template <class ELFT> void Writer<ELFT>:
// Define __rel[a]_iplt_{start,end} symbols if needed.
addRelIpltSymbols();
+ if (Out<ELFT>::EhFrameHdr->Sec)
+ Out<ELFT>::EhFrameHdr->Sec->finalize();
+
// 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<elf::ObjectFile<ELFT>> &F :
- Symtab.getObjectFiles()) {
- for (InputSectionBase<ELFT> *C : F->getSections()) {
- if (isDiscarded(C))
- continue;
- if (auto *S = dyn_cast<InputSection<ELFT>>(C))
- scanRelocs(*S);
- else if (auto *S = dyn_cast<EHInputSection<ELFT>>(C))
- if (S->RelocSection)
- scanRelocs(*S, *S->RelocSection);
- }
+ for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+ Sec->forEachInputSection([&](InputSectionBase<ELFT> *S) {
+ if (auto *IS = dyn_cast<InputSection<ELFT>>(S)) {
+ // Set OutSecOff so that scanRelocs can use it.
+ uintX_t Off = alignTo(Sec->getSize(), S->Align);
+ IS->OutSecOff = Off;
+
+ scanRelocs(*IS);
+
+ // Now that scan relocs possibly changed the size, update the offset.
+ Sec->setSize(Off + S->getSize());
+ } else if (auto *EH = dyn_cast<EHInputSection<ELFT>>(S)) {
+ if (EH->RelocSection)
+ scanRelocs(*EH, *EH->RelocSection);
+ }
+ });
}
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
- Sec->assignOffsets();
-
// Now that we have defined all possible symbols including linker-
// synthesized ones. Visit all symbols to give the finishing touches.
std::vector<DefinedCommon *> CommonSymbols;
Added: lld/trunk/test/ELF/eh-frame-dyn-rel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/eh-frame-dyn-rel.s?rev=265673&view=auto
==============================================================================
--- lld/trunk/test/ELF/eh-frame-dyn-rel.s (added)
+++ lld/trunk/test/ELF/eh-frame-dyn-rel.s Thu Apr 7 09:22:09 2016
@@ -0,0 +1,13 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o %t.o -o %t -shared
+// RUN: llvm-readobj -r %t | FileCheck %s
+
+ .section bar,"axG", at progbits,foo,comdat
+ .cfi_startproc
+ .cfi_personality 0x8c, foo
+ .cfi_endproc
+
+// CHECK: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x1DA R_X86_64_64 foo 0x0
+// CHECK-NEXT: }
More information about the llvm-commits
mailing list