From: Rafael Espindola Date: Thu, 7 Apr 2016 14:22:09 +0000 (+0000) Subject: Don't create dynamic relocs for discarded .eh_frame entries. X-Git-Tag: llvmorg-3.9.0-rc1~9740 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56004c577a05b7cfe504a2251731ebdb4fb0803f;p=platform%2Fupstream%2Fllvm.git 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 --- diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 18d1ed4..feaff82 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -307,7 +307,7 @@ typename ELFT::uint DynamicReloc::getOffset() const { case Off_LTlsIndex: return Out::Got->getTlsIndexVA(); case Off_Sec: - return OffsetSec->getOffset(OffsetInSec) + OffsetSec->OutSec->getVA(); + return OffsetInSec + OffsetSec->getVA(); case Off_Bss: return cast>(Sym)->OffsetInBss + Out::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 void OutputSection::assignOffsets() { - uintX_t Off = this->Header.sh_size; - for (InputSection *S : Sections) { - Off = alignTo(Off, S->Align); - S->OutSecOff = Off; - Off += S->getSize(); - } - this->Header.sh_size = Off; +template +void OutputSection::forEachInputSection( + std::function *S)> F) { + for (InputSection *S : Sections) + F(S); } // Sorts input sections by section name suffixes, so that .foo.N comes @@ -956,6 +951,13 @@ EHOutputSection::EHOutputSection(StringRef Name, uint32_t Type, } template +void EHOutputSection::forEachInputSection( + std::function *)> F) { + for (EHInputSection *S : Sections) + F(S); +} + +template EHRegion::EHRegion(EHInputSection *S, unsigned Index) : S(S), Index(Index) {} @@ -1186,31 +1188,43 @@ void EHOutputSection::addSection(InputSectionBase *C) { } template -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(Buf, Len - 4); memcpy(Buf + 4, Data.data() + 4, Data.size() - 4); - return Len; } -template void EHOutputSection::writeTo(uint8_t *Buf) { - const endianness E = ELFT::TargetEndianness; +template void EHOutputSection::finalize() { + if (Finalized) + return; + Finalized = true; + size_t Offset = 0; for (const Cie &C : Cies) { - size_t CieOffset = Offset; - - uintX_t CIELen = writeAlignedCieOrFde(C.data(), Buf + Offset); C.S->Offsets[C.Index].second = Offset; - Offset += CIELen; + Offset += alignTo(C.data().size(), sizeof(uintX_t)); for (const EHRegion &F : C.Fdes) { - uintX_t Len = writeAlignedCieOrFde(F.data(), Buf + Offset); - write32(Buf + Offset + 4, Offset + 4 - CieOffset); // Pointer F.S->Offsets[F.Index].second = Offset; + Offset += alignTo(F.data().size(), sizeof(uintX_t)); + } + } +} + +template void EHOutputSection::writeTo(uint8_t *Buf) { + const endianness E = ELFT::TargetEndianness; + for (const Cie &C : Cies) { + size_t CieOffset = C.S->Offsets[C.Index].second; + writeAlignedCieOrFde(C.data(), Buf + CieOffset); + + for (const EHRegion &F : C.Fdes) { + size_t Offset = F.S->Offsets[F.Index].second; + writeAlignedCieOrFde(F.data(), Buf + Offset); + write32(Buf + Offset + 4, Offset + 4 - CieOffset); // Pointer + Out::EhFrameHdr->addFde(C.FdeEncoding, Offset, Buf + Offset + 8); - Offset += Len; } } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 8a48ba8..95b6790 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 *)> F) {} virtual void writeTo(uint8_t *Buf) {} virtual ~OutputSectionBase() = default; @@ -183,7 +184,7 @@ template struct DynamicReloc { } OKind; SymbolBody *Sym = nullptr; - InputSectionBase *OffsetSec = nullptr; + OutputSectionBase *OffsetSec = nullptr; uintX_t OffsetInSec = 0; bool UseSymVA = false; uintX_t Addend = 0; @@ -194,7 +195,7 @@ template 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 *OffsetSec, + DynamicReloc(uint32_t Type, OutputSectionBase *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 *)> F) override; std::vector *> 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 *)> F) override; template void addSectionAux(EHInputSection *S, llvm::ArrayRef Rels); @@ -335,6 +338,7 @@ private: // Maps CIE content + personality to a index in Cies. llvm::DenseMap, unsigned> CieMap; + bool Finalized = false; }; template @@ -493,6 +497,8 @@ public: bool Live = false; + EHOutputSection *Sec = nullptr; + private: struct FdeData { uint8_t Enc; @@ -502,7 +508,6 @@ private: uintX_t getFdePc(uintX_t EhVA, const FdeData &F); - EHOutputSection *Sec = nullptr; std::vector FdeList; }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 27a1e0f..7d12a32 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -349,6 +349,10 @@ void Writer::scanRelocs(InputSectionBase &C, ArrayRef 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::scanRelocs(InputSectionBase &C, ArrayRef Rels) { } if (Target->needsDynRelative(Type)) - Out::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, true, + Out::RelaDyn->addReloc({Target->RelativeRel, C.OutSec, Offset, true, &Body, getAddend(RI)}); // If a symbol in a DSO is referenced directly instead of through GOT, @@ -447,7 +451,7 @@ void Writer::scanRelocs(InputSectionBase &C, ArrayRef Rels) { if (Preemptible) { // We don't know anything about the finaly symbol. Just ask the dynamic // linker to handle the relocation for us. - Out::RelaDyn->addReloc({Target->getDynRel(Type), &C, RI.r_offset, + Out::RelaDyn->addReloc({Target->getDynRel(Type), C.OutSec, Offset, false, &Body, getAddend(RI)}); continue; } @@ -464,13 +468,13 @@ void Writer::scanRelocs(InputSectionBase &C, ArrayRef Rels) { uintX_t Addend = getAddend(RI); if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC) { - Out::RelaDyn->addReloc({R_PPC64_RELATIVE, &C, RI.r_offset, false, + Out::RelaDyn->addReloc({R_PPC64_RELATIVE, C.OutSec, Offset, false, nullptr, (uintX_t)getPPC64TocBase() + Addend}); continue; } Out::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 void Writer::createSections() { // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); + if (Out::EhFrameHdr->Sec) + Out::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> &F : - Symtab.getObjectFiles()) { - for (InputSectionBase *C : F->getSections()) { - if (isDiscarded(C)) - continue; - if (auto *S = dyn_cast>(C)) - scanRelocs(*S); - else if (auto *S = dyn_cast>(C)) - if (S->RelocSection) - scanRelocs(*S, *S->RelocSection); - } + for (OutputSectionBase *Sec : OutputSections) { + Sec->forEachInputSection([&](InputSectionBase *S) { + if (auto *IS = dyn_cast>(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>(S)) { + if (EH->RelocSection) + scanRelocs(*EH, *EH->RelocSection); + } + }); } - for (OutputSectionBase *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 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 0000000..47827a7 --- /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: }