diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2016-04-07 14:22:09 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2016-04-07 14:22:09 +0000 |
| commit | 56004c577a05b7cfe504a2251731ebdb4fb0803f (patch) | |
| tree | 7f12686c5c829350e68dd276646ef871ece685a5 /lld | |
| parent | 0ab420570500273e2814a21f65075257b319b59b (diff) | |
| download | bcm5719-llvm-56004c577a05b7cfe504a2251731ebdb4fb0803f.tar.gz bcm5719-llvm-56004c577a05b7cfe504a2251731ebdb4fb0803f.zip | |
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.
llvm-svn: 265673
Diffstat (limited to 'lld')
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 58 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.h | 19 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 45 | ||||
| -rw-r--r-- | lld/test/ELF/eh-frame-dyn-rel.s | 13 |
4 files changed, 88 insertions, 47 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 18d1ed47350..feaff820d86 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -307,7 +307,7 @@ typename ELFT::uint DynamicReloc<ELFT>::getOffset() const { 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(StringRef Name, uint32_t Type, } 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(InputSectionBase<ELFT> *C) { } 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; } } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 8a48ba8e193..95b679013a4 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -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 DynamicReloc { } 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 DynamicReloc { 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; }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 27a1e0f4f6b..7d12a32e794 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -349,6 +349,10 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { 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(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { } 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(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { 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(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { 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>::createSections() { // 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; diff --git a/lld/test/ELF/eh-frame-dyn-rel.s b/lld/test/ELF/eh-frame-dyn-rel.s new file mode 100644 index 00000000000..47827a7143a --- /dev/null +++ b/lld/test/ELF/eh-frame-dyn-rel.s @@ -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",@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: } |

