[lld] r244969 - Make OutputSection virtual and use that for creating the string table.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 13 15:14:37 PDT 2015


Author: rafael
Date: Thu Aug 13 17:14:37 2015
New Revision: 244969

URL: http://llvm.org/viewvc/llvm-project?rev=244969&view=rev
Log:
Make OutputSection virtual and use that for creating the string table.

We were creating the string table in a completely ad hoc way. Now the
string table is an output section and gets its output offset set just like
any other section.

This opens the way for other linker created sections like the symbol table.

Modified:
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=244969&r1=244968&r2=244969&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Aug 13 17:14:37 2015
@@ -32,13 +32,13 @@ namespace {
 // Chunks cannot belong to more than one OutputSections. The writer
 // creates multiple OutputSections and assign them unique,
 // non-overlapping file offsets and VAs.
-template <bool Is64Bits> class OutputSection {
+template <bool Is64Bits> class OutputSectionBase {
 public:
   typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
   typedef
       typename std::conditional<Is64Bits, Elf64_Shdr, Elf32_Shdr>::type HeaderT;
 
-  OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
+  OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
       : Name(Name) {
     memset(&Header, 0, sizeof(HeaderT));
     Header.sh_type = sh_type;
@@ -46,8 +46,6 @@ public:
   }
   void setVA(uintX_t VA) { Header.sh_addr = VA; }
   void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
-  void addChunk(Chunk *C);
-  std::vector<Chunk *> &getChunks() { return Chunks; }
   template <endianness E>
   void writeHeaderTo(typename ELFFile<ELFType<E, Is64Bits>>::Elf_Shdr *SHdr);
   StringRef getName() { return Name; }
@@ -59,12 +57,49 @@ public:
   uintX_t getOffset() { return Header.sh_offset; }
   uintX_t getAlign() { return Header.sh_addralign; }
 
-private:
+  virtual void finalize() {}
+  virtual void writeTo(uint8_t *Buf) = 0;
+
+protected:
   StringRef Name;
   HeaderT Header;
+  ~OutputSectionBase() = default;
+};
+
+template <bool Is64Bits>
+class OutputSection final : public OutputSectionBase<Is64Bits> {
+public:
+  typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
+  OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
+      : OutputSectionBase<Is64Bits>(Name, sh_type, sh_flags) {}
+
+  void addChunk(Chunk *C);
+  void writeTo(uint8_t *Buf) override;
+
+private:
   std::vector<Chunk *> Chunks;
 };
 
+template <bool Is64Bits>
+class StringTableSection final : public OutputSectionBase<Is64Bits> {
+  llvm::StringTableBuilder StrTabBuilder;
+
+public:
+  typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
+  StringTableSection() : OutputSectionBase<Is64Bits>(".strtab", SHT_STRTAB, 0) {
+    this->Header.sh_addralign = 1;
+  }
+
+  void add(StringRef S) { StrTabBuilder.add(S); }
+  size_t getOffset(StringRef S) { return StrTabBuilder.getOffset(S); }
+  void writeTo(uint8_t *Buf) override;
+
+  void finalize() override {
+    StrTabBuilder.finalize(StringTableBuilder::ELF);
+    this->Header.sh_size = StrTabBuilder.data().size();
+  }
+};
+
 // The writer writes a SymbolTable result to a file.
 template <class ELFT> class Writer {
 public:
@@ -83,14 +118,15 @@ private:
   SymbolTable *Symtab;
   std::unique_ptr<llvm::FileOutputBuffer> Buffer;
   llvm::SpecificBumpPtrAllocator<OutputSection<ELFT::Is64Bits>> CAlloc;
-  std::vector<OutputSection<ELFT::Is64Bits> *> OutputSections;
+  std::vector<OutputSectionBase<ELFT::Is64Bits> *> OutputSections;
 
   uintX_t FileSize;
   uintX_t SizeOfHeaders;
   uintX_t SectionHeaderOff;
-  uintX_t StringTableOff;
+
   unsigned StringTableIndex;
-  StringTableBuilder StrTabBuilder;
+  StringTableSection<ELFT::Is64Bits> StringTable;
+
   unsigned NumSections;
 };
 } // anonymous namespace
@@ -122,19 +158,30 @@ template <class ELFT> void Writer<ELFT>:
 template <bool Is64Bits> void OutputSection<Is64Bits>::addChunk(Chunk *C) {
   Chunks.push_back(C);
   uint32_t Align = C->getAlign();
-  if (Align > Header.sh_addralign)
-    Header.sh_addralign = Align;
+  if (Align > this->Header.sh_addralign)
+    this->Header.sh_addralign = Align;
 
-  uintX_t Off = Header.sh_size;
+  uintX_t Off = this->Header.sh_size;
   Off = RoundUpToAlignment(Off, Align);
   C->setOutputSectionOff(Off);
   Off += C->getSize();
-  Header.sh_size = Off;
+  this->Header.sh_size = Off;
+}
+
+template <bool Is64Bits> void OutputSection<Is64Bits>::writeTo(uint8_t *Buf) {
+  for (Chunk *C : Chunks)
+    C->writeTo(Buf);
+}
+
+template <bool Is64Bits>
+void StringTableSection<Is64Bits>::writeTo(uint8_t *Buf) {
+  StringRef Data = StrTabBuilder.data();
+  memcpy(Buf, Data.data(), Data.size());
 }
 
 template <bool Is64Bits>
 template <endianness E>
-void OutputSection<Is64Bits>::writeHeaderTo(
+void OutputSectionBase<Is64Bits>::writeHeaderTo(
     typename ELFFile<ELFType<E, Is64Bits>>::Elf_Shdr *SHdr) {
   SHdr->sh_name = Header.sh_name;
   SHdr->sh_type = Header.sh_type;
@@ -198,7 +245,8 @@ template <class ELFT> void Writer<ELFT>:
 }
 
 template <bool Is64Bits>
-static bool compSec(OutputSection<Is64Bits> *A, OutputSection<Is64Bits> *B) {
+static bool compSec(OutputSectionBase<Is64Bits> *A,
+                    OutputSectionBase<Is64Bits> *B) {
   // Place SHF_ALLOC sections first.
   return (A->getFlags() & SHF_ALLOC) && !(B->getFlags() & SHF_ALLOC);
 }
@@ -213,7 +261,13 @@ template <class ELFT> void Writer<ELFT>:
   std::stable_sort(OutputSections.begin(), OutputSections.end(),
                    compSec<ELFT::Is64Bits>);
 
-  for (OutputSection<ELFT::Is64Bits> *Sec : OutputSections) {
+  OutputSections.push_back(&StringTable);
+  StringTableIndex = OutputSections.size();
+
+  for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections) {
+    StringTable.add(Sec->getName());
+    Sec->finalize();
+
     uintX_t Align = Sec->getAlign();
     uintX_t Size = Sec->getSize();
     if (Sec->getFlags() & SHF_ALLOC) {
@@ -222,7 +276,6 @@ template <class ELFT> void Writer<ELFT>:
     }
     Sec->setFileOffset(FileOff);
     FileOff += RoundUpToAlignment(Size, Align);
-    StrTabBuilder.add(Sec->getName());
   }
 
   // Regular sections.
@@ -231,14 +284,6 @@ template <class ELFT> void Writer<ELFT>:
   // First dummy section.
   NumSections++;
 
-  // String table.
-  StrTabBuilder.add(".strtab");
-  StringTableIndex = NumSections;
-  StringTableOff = FileOff;
-  StrTabBuilder.finalize(StringTableBuilder::ELF);
-  FileOff += StrTabBuilder.data().size();
-  NumSections++;
-
   FileOff += OffsetToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
 
   // Add space for section headers.
@@ -288,22 +333,10 @@ template <class ELFT> void Writer<ELFT>:
   auto SHdrs = reinterpret_cast<Elf_Shdr_Impl<ELFT> *>(Buf + EHdr->e_shoff);
   // First entry is null.
   ++SHdrs;
-  for (OutputSection<ELFT::Is64Bits> *Sec : OutputSections) {
-    Sec->setNameOffset(StrTabBuilder.getOffset(Sec->getName()));
+  for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections) {
+    Sec->setNameOffset(StringTable.getOffset(Sec->getName()));
     Sec->template writeHeaderTo<ELFT::TargetEndianness>(SHdrs++);
   }
-
-  // String table.
-  SHdrs->sh_name = StrTabBuilder.getOffset(".strtab");
-  SHdrs->sh_type = SHT_STRTAB;
-  SHdrs->sh_flags = 0;
-  SHdrs->sh_addr = 0;
-  SHdrs->sh_offset = StringTableOff;
-  SHdrs->sh_size = StrTabBuilder.data().size();
-  SHdrs->sh_link = 0;
-  SHdrs->sh_info = 0;
-  SHdrs->sh_addralign = 1;
-  SHdrs->sh_entsize = 0;
 }
 
 template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) {
@@ -316,13 +349,6 @@ template <class ELFT> void Writer<ELFT>:
 // Write section contents to a mmap'ed file.
 template <class ELFT> void Writer<ELFT>::writeSections() {
   uint8_t *Buf = Buffer->getBufferStart();
-  for (OutputSection<ELFT::Is64Bits> *Sec : OutputSections) {
-    uint8_t *SecBuf = Buf + Sec->getOffset();
-    for (Chunk *C : Sec->getChunks())
-      C->writeTo(SecBuf);
-  }
-
-  // String table.
-  StringRef Data = StrTabBuilder.data();
-  memcpy(Buf + StringTableOff, Data.data(), Data.size());
+  for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections)
+    Sec->writeTo(Buf + Sec->getOffset());
 }




More information about the llvm-commits mailing list