[lld] r285148 - Read section headers upfront.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 25 17:54:04 PDT 2016


Author: rafael
Date: Tue Oct 25 19:54:03 2016
New Revision: 285148

URL: http://llvm.org/viewvc/llvm-project?rev=285148&view=rev
Log:
Read section headers upfront.

Instead of storing a pointer, store the members we need.

The reason for doing this is that it makes it far easier to create
synthetic sections. It also avoids reading data from files multiple
times., which might help with cross endian linking and host
architectures with slow unaligned access.

There are obvious compacting opportunities, but this already has mixed
results even on native x86_64 linking.

There is also the possibility of better refactoring the code for
handling common symbols, but this already shows that a custom class is
not necessary.

Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=285148&r1=285147&r2=285148&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Oct 25 19:54:03 2016
@@ -33,28 +33,31 @@ template <class ELFT>
 static ArrayRef<uint8_t> getSectionContents(elf::ObjectFile<ELFT> *File,
                                             const typename ELFT::Shdr *Hdr) {
   if (!File || Hdr->sh_type == SHT_NOBITS)
-    return {};
+    return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size);
   return check(File->getObj().getSectionContents(Hdr));
 }
 
 // ELF supports ZLIB-compressed section. Returns true if the section
 // is compressed.
 template <class ELFT>
-static bool isCompressed(const typename ELFT::Shdr *Hdr, StringRef Name) {
-  return (Hdr->sh_flags & SHF_COMPRESSED) || Name.startswith(".zdebug");
+static bool isCompressed(typename ELFT::uint Flags, StringRef Name) {
+  return (Flags & SHF_COMPRESSED) || Name.startswith(".zdebug");
 }
 
 template <class ELFT>
 InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
-                                         const Elf_Shdr *Hdr, StringRef Name,
+                                         uintX_t Flags, uint32_t Type,
+                                         uintX_t Entsize, uint32_t Link,
+                                         uint32_t Info, uintX_t Addralign,
+                                         ArrayRef<uint8_t> Data, StringRef Name,
                                          Kind SectionKind)
-    : InputSectionData(SectionKind, Name, getSectionContents(File, Hdr),
-                       isCompressed<ELFT>(Hdr, Name),
-                       !Config->GcSections || !(Hdr->sh_flags & SHF_ALLOC)),
-      Header(Hdr), File(File), Repl(this) {
+    : InputSectionData(SectionKind, Name, Data, isCompressed<ELFT>(Flags, Name),
+                       !Config->GcSections || !(Flags & SHF_ALLOC)),
+      File(File), Flags(Flags), Entsize(Entsize), Type(Type), Link(Link),
+      Info(Info), Repl(this) {
   // The ELF spec states that a value of 0 means the section has
   // no alignment constraits.
-  uint64_t V = std::max<uint64_t>(Hdr->sh_addralign, 1);
+  uint64_t V = std::max<uint64_t>(Addralign, 1);
   if (!isPowerOf2_64(V))
     fatal(getFilename(File) + ": section sh_addralign is not a power of 2");
 
@@ -66,11 +69,19 @@ InputSectionBase<ELFT>::InputSectionBase
   Alignment = V;
 }
 
+template <class ELFT>
+InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
+                                         const Elf_Shdr *Hdr, StringRef Name,
+                                         Kind SectionKind)
+    : InputSectionBase(File, Hdr->sh_flags, Hdr->sh_type, Hdr->sh_entsize,
+                       Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign,
+                       getSectionContents(File, Hdr), Name, SectionKind) {}
+
 template <class ELFT> size_t InputSectionBase<ELFT>::getSize() const {
   if (auto *D = dyn_cast<InputSection<ELFT>>(this))
     if (D->getThunksSize() > 0)
       return D->getThunkOff() + D->getThunksSize();
-  return Header->sh_size;
+  return Data.size();
 }
 
 // Returns a string for an error message.
@@ -177,6 +188,13 @@ InputSectionBase<ELFT> *InputSectionBase
 }
 
 template <class ELFT>
+InputSection<ELFT>::InputSection(uintX_t Flags, uint32_t Type,
+                                 uintX_t Addralign, ArrayRef<uint8_t> Data)
+    : InputSectionBase<ELFT>(nullptr, Flags, Type,
+                             /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Addralign,
+                             Data, "", Base::Regular) {}
+
+template <class ELFT>
 InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F,
                                  const Elf_Shdr *Header, StringRef Name)
     : InputSectionBase<ELFT>(F, Header, Name, Base::Regular) {}
@@ -198,7 +216,7 @@ template <class ELFT> void InputSection<
 }
 
 template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const {
-  return this->Header->sh_size;
+  return this->Data.size();
 }
 
 template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const {
@@ -458,15 +476,14 @@ void InputSectionBase<ELFT>::relocate(ui
 template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) {
   if (this->getType() == SHT_NOBITS)
     return;
-  ELFFile<ELFT> &EObj = this->File->getObj();
 
   // If -r is given, then an InputSection may be a relocation section.
   if (this->getType() == SHT_RELA) {
-    copyRelocations(Buf + OutSecOff, EObj.relas(this->Header));
+    copyRelocations(Buf + OutSecOff, this->template getDataAs<Elf_Rela>());
     return;
   }
   if (this->getType() == SHT_REL) {
-    copyRelocations(Buf + OutSecOff, EObj.rels(this->Header));
+    copyRelocations(Buf + OutSecOff, this->template getDataAs<Elf_Rel>());
     return;
   }
 
@@ -804,27 +821,28 @@ bool MipsAbiFlagsInputSection<ELFT>::cla
 }
 
 template <class ELFT>
-CommonInputSection<ELFT>::CommonInputSection(std::vector<DefinedCommon *> Syms)
-    : InputSection<ELFT>(nullptr, &Hdr, "") {
-  Hdr.sh_size = 0;
-  Hdr.sh_type = SHT_NOBITS;
-  Hdr.sh_flags = SHF_ALLOC | SHF_WRITE;
-  this->Live = true;
-
+InputSection<ELFT> InputSection<ELFT>::createCommonInputSection(
+    std::vector<DefinedCommon *> Syms) {
   // Sort the common symbols by alignment as an heuristic to pack them better.
   std::stable_sort(Syms.begin(), Syms.end(),
                    [](const DefinedCommon *A, const DefinedCommon *B) {
                      return A->Alignment > B->Alignment;
                    });
 
+  size_t Size = 0;
+  uintX_t Alignment = 1;
   for (DefinedCommon *Sym : Syms) {
-    this->Alignment = std::max<uintX_t>(this->Alignment, Sym->Alignment);
-    Hdr.sh_size = alignTo(Hdr.sh_size, Sym->Alignment);
+    Alignment = std::max<uintX_t>(Alignment, Sym->Alignment);
+    Size = alignTo(Size, Sym->Alignment);
 
     // Compute symbol offset relative to beginning of input section.
-    Sym->Offset = Hdr.sh_size;
-    Hdr.sh_size += Sym->Size;
+    Sym->Offset = Size;
+    Size += Sym->Size;
   }
+  ArrayRef<uint8_t> Data = makeArrayRef<uint8_t>(nullptr, Size);
+  InputSection Ret(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Data);
+  Ret.Live = true;
+  return Ret;
 }
 
 template class elf::InputSectionBase<ELF32LE>;
@@ -861,8 +879,3 @@ template class elf::MipsAbiFlagsInputSec
 template class elf::MipsAbiFlagsInputSection<ELF32BE>;
 template class elf::MipsAbiFlagsInputSection<ELF64LE>;
 template class elf::MipsAbiFlagsInputSection<ELF64BE>;
-
-template class elf::CommonInputSection<ELF32LE>;
-template class elf::CommonInputSection<ELF32BE>;
-template class elf::CommonInputSection<ELF64LE>;
-template class elf::CommonInputSection<ELF64BE>;

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=285148&r1=285147&r2=285148&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Tue Oct 25 19:54:03 2016
@@ -60,6 +60,12 @@ public:
   StringRef Name;
   ArrayRef<uint8_t> Data;
 
+  template <typename T> llvm::ArrayRef<T> getDataAs() const {
+    size_t S = Data.size();
+    assert(S % sizeof(T) == 0);
+    return llvm::makeArrayRef<T>((const T *)Data.data(), S / sizeof(T));
+  }
+
   // If a section is compressed, this has the uncompressed section data.
   std::unique_ptr<uint8_t[]> UncompressedData;
 
@@ -75,11 +81,17 @@ protected:
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::uint uintX_t;
-  const Elf_Shdr *Header;
 
   // The file this section is from.
   ObjectFile<ELFT> *File;
 
+  // These corresponds to the fields in Elf_Shdr.
+  uintX_t Flags;
+  uintX_t Entsize;
+  uint32_t Type;
+  uint32_t Link;
+  uint32_t Info;
+
 public:
   InputSectionBase()
       : InputSectionData(Regular, "", ArrayRef<uint8_t>(), false, false),
@@ -87,6 +99,10 @@ public:
 
   InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
                    StringRef Name, Kind SectionKind);
+  InputSectionBase(ObjectFile<ELFT> *File, uintX_t Flags, uint32_t Type,
+                   uintX_t Entsize, uint32_t Link, uint32_t Info,
+                   uintX_t Addralign, ArrayRef<uint8_t> Data, StringRef Name,
+                   Kind SectionKind);
   OutputSectionBase<ELFT> *OutSec = nullptr;
 
   // This pointer points to the "real" instance of this instance.
@@ -101,11 +117,11 @@ public:
 
   static InputSectionBase<ELFT> Discarded;
 
-  uintX_t getFlags() const { return Header->sh_flags; }
-  uint32_t getType() const { return Header->sh_type; }
-  uintX_t getEntsize() const { return Header->sh_entsize; }
-  uint32_t getLink() const { return Header->sh_link; }
-  uint32_t getInfo() const { return Header->sh_info; }
+  uintX_t getFlags() const { return Flags; }
+  uint32_t getType() const { return Type; }
+  uintX_t getEntsize() const { return Entsize; }
+  uint32_t getLink() const { return Link; }
+  uint32_t getInfo() const { return Info; }
   ObjectFile<ELFT> *getFile() const { return File; }
   uintX_t getOffset(const DefinedRegular<ELFT> &Sym) const;
   InputSectionBase *getLinkOrderDep() const;
@@ -225,6 +241,8 @@ template <class ELFT> class InputSection
   typedef typename ELFT::uint uintX_t;
 
 public:
+  InputSection(uintX_t Flags, uint32_t Type, uintX_t Addralign,
+               ArrayRef<uint8_t> Data);
   InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header, StringRef Name);
 
   // Write this section to a mmap'ed file, assuming Buf is pointing to
@@ -259,6 +277,14 @@ public:
   template <class RelTy>
   void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
 
+  // Common symbols don't belong to any section. But it is easier for us
+  // to handle them as if they belong to some input section. So we defined
+  // this section that "contains" all common symbols.
+  static InputSection<ELFT> *CommonInputSection;
+
+  static InputSection<ELFT>
+  createCommonInputSection(std::vector<DefinedCommon *> Syms);
+
 private:
   template <class RelTy>
   void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
@@ -272,6 +298,9 @@ private:
   llvm::TinyPtrVector<const Thunk<ELFT> *> Thunks;
 };
 
+template <class ELFT>
+InputSection<ELFT> *InputSection<ELFT>::CommonInputSection;
+
 // MIPS .reginfo section provides information on the registers used by the code
 // in the object file. Linker should collect this information and write a single
 // .reginfo section in the output file. The output section contains a union of
@@ -314,26 +343,6 @@ public:
   const llvm::object::Elf_Mips_ABIFlags<ELFT> *Flags = nullptr;
 };
 
-// Common symbols don't belong to any section. But it is easier for us
-// to handle them as if they belong to some input section. So we defined
-// this class. CommonInputSection is a virtual singleton class that
-// "contains" all common symbols.
-template <class ELFT> class CommonInputSection : public InputSection<ELFT> {
-  typedef typename ELFT::uint uintX_t;
-
-public:
-  CommonInputSection(std::vector<DefinedCommon *> Syms);
-
-  // The singleton instance of this class.
-  static CommonInputSection<ELFT> *X;
-
-private:
-  static typename ELFT::Shdr Hdr;
-};
-
-template <class ELFT> CommonInputSection<ELFT> *CommonInputSection<ELFT>::X;
-template <class ELFT> typename ELFT::Shdr CommonInputSection<ELFT>::Hdr;
-
 } // namespace elf
 } // namespace lld
 

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=285148&r1=285147&r2=285148&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Tue Oct 25 19:54:03 2016
@@ -184,7 +184,7 @@ void LinkerScript<ELFT>::computeInputSec
         if (!isDiscarded(S) && !S->OutSec && Pat.SectionRe.match(S->Name))
           I->Sections.push_back(S);
       if (Pat.SectionRe.match("COMMON"))
-        I->Sections.push_back(CommonInputSection<ELFT>::X);
+        I->Sections.push_back(InputSection<ELFT>::CommonInputSection);
     }
 
     // Sort sections as instructed by SORT-family commands and --sort-section

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=285148&r1=285147&r2=285148&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Oct 25 19:54:03 2016
@@ -1565,7 +1565,7 @@ SymbolTableSection<ELFT>::getOutputSecti
     break;
   }
   case SymbolBody::DefinedCommonKind:
-    return CommonInputSection<ELFT>::X->OutSec;
+    return InputSection<ELFT>::CommonInputSection->OutSec;
   case SymbolBody::SharedKind:
     if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy())
       return Out<ELFT>::Bss;

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=285148&r1=285147&r2=285148&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue Oct 25 19:54:03 2016
@@ -69,8 +69,8 @@ static typename ELFT::uint getSymVA(cons
     return VA;
   }
   case SymbolBody::DefinedCommonKind:
-    return CommonInputSection<ELFT>::X->OutSec->getVA() +
-           CommonInputSection<ELFT>::X->OutSecOff +
+    return InputSection<ELFT>::CommonInputSection->OutSec->getVA() +
+           InputSection<ELFT>::CommonInputSection->OutSecOff +
            cast<DefinedCommon>(Body).Offset;
   case SymbolBody::SharedKind: {
     auto &SS = cast<SharedSymbol<ELFT>>(Body);

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=285148&r1=285147&r2=285148&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Oct 25 19:54:03 2016
@@ -261,8 +261,9 @@ template <class ELFT> void Writer<ELFT>:
   if (Target->NeedsThunks)
     forEachRelSec(createThunks<ELFT>);
 
-  CommonInputSection<ELFT> Common(getCommonSymbols<ELFT>());
-  CommonInputSection<ELFT>::X = &Common;
+  InputSection<ELFT> Common =
+      InputSection<ELFT>::createCommonInputSection(getCommonSymbols<ELFT>());
+  InputSection<ELFT>::CommonInputSection = &Common;
 
   Script<ELFT>::X->OutputSections = &OutputSections;
   if (ScriptConfig->HasSections) {
@@ -825,8 +826,8 @@ template <class ELFT> void Writer<ELFT>:
 
   // If linker script processor hasn't added common symbol section yet,
   // then add it to .bss now.
-  if (!CommonInputSection<ELFT>::X->OutSec) {
-    Out<ELFT>::Bss->addSection(CommonInputSection<ELFT>::X);
+  if (!InputSection<ELFT>::CommonInputSection->OutSec) {
+    Out<ELFT>::Bss->addSection(InputSection<ELFT>::CommonInputSection);
     Out<ELFT>::Bss->assignOffsets();
   }
 




More information about the llvm-commits mailing list