[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