[lld] r251152 - ELF2: Simplify Writer::assignAddresses. NFC.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 23 14:45:59 PDT 2015


Author: ruiu
Date: Fri Oct 23 16:45:59 2015
New Revision: 251152

URL: http://llvm.org/viewvc/llvm-project?rev=251152&view=rev
Log:
ELF2: Simplify Writer::assignAddresses. NFC.

This patch is an attempt to simplify assignAddresses function by splitting
it and using less variables. I tried to split the code to create PHDRs from
the code to assign addresses, but it didn't make this code simpler, so I
didn't do that in this patch.

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=251152&r1=251151&r2=251152&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Oct 23 16:45:59 2015
@@ -67,6 +67,7 @@ private:
     return !Symtab.getSharedFiles().empty() || Config->Shared;
   }
   uintX_t getVAStart() const { return Config->Shared ? 0 : Target->getVAStart(); }
+  int getPhdrsNum() const;
 
   std::unique_ptr<llvm::FileOutputBuffer> Buffer;
 
@@ -78,7 +79,7 @@ private:
 
   void addStartStopSymbols(OutputSectionBase<ELFT> *Sec);
   void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff,
-               uintX_t VA, uintX_t Align);
+               uintX_t VA, uintX_t Size, uintX_t Align);
   void copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From);
 
   SymbolTable<ELFT> &Symtab;
@@ -603,58 +604,38 @@ template <class ELFT> static bool needsP
   return Sec->getFlags() & SHF_ALLOC;
 }
 
-// Visits all sections to assign incremental, non-overlapping RVAs and
-// file offsets.
+// Visits all sections to create PHDRs and to assign incremental,
+// non-overlapping addresses to output sections.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
-  assert(!OutputSections.empty() && "No output sections to layout!");
   uintX_t VA = getVAStart() + sizeof(Elf_Ehdr);
   uintX_t FileOff = sizeof(Elf_Ehdr);
 
-  // Reserve space for Phdrs.
-  int NumPhdrs = 2;   // 2 for PhdrPhdr and FileHeaderPhdr
-  if (needsInterpSection())
-    ++NumPhdrs;
-  if (isOutputDynamic())
-    ++NumPhdrs;
-  uintX_t Last = PF_R;
-  for (OutputSectionBase<ELFT> *Sec : OutputSections) {
-    if (!Sec->getSize() || !needsPhdr<ELFT>(Sec))
-      continue;
-    uintX_t Flags = toPhdrFlags(Sec->getFlags());
-    if (Last != Flags) {
-      Last = Flags;
-      ++NumPhdrs;
-    }
-  }
-
-  // Reserve space needed for the program header so that the array
-  // will never be resized.
-  Phdrs.reserve(NumPhdrs);
-
-  // The first Phdr entry is PT_PHDR which describes the program header itself.
-  Phdrs.emplace_back();
-  Elf_Phdr *PhdrPhdr = &Phdrs.back();
-  setPhdr(PhdrPhdr, PT_PHDR, PF_R, FileOff, VA, /*Align=*/8);
-
-  FileOff += sizeof(Elf_Phdr) * NumPhdrs;
-  VA += sizeof(Elf_Phdr) * NumPhdrs;
+  // Calculate and reserve the space for the program header first so that
+  // the first section can start right after the program header.
+  Phdrs.resize(getPhdrsNum());
+  size_t PhdrSize = sizeof(Elf_Phdr) * Phdrs.size();
+
+  // The first phdr entry is PT_PHDR which describes the program header itself.
+  setPhdr(&Phdrs[0], PT_PHDR, PF_R, FileOff, VA, PhdrSize, /*Align=*/8);
+  FileOff += PhdrSize;
+  VA += PhdrSize;
 
+  // PT_INTERP must be the second entry if exists.
+  int PhdrIdx = 0;
   Elf_Phdr *Interp = nullptr;
-  if (needsInterpSection()) {
-    Phdrs.emplace_back();
-    Interp = &Phdrs.back();
-  }
+  if (needsInterpSection())
+    Interp = &Phdrs[++PhdrIdx];
 
-  // Create a Phdr for the file header.
-  Phdrs.emplace_back();
-  Elf_Phdr *FileHeader = &Phdrs.back();
-  setPhdr(FileHeader, PT_LOAD, PF_R, 0, getVAStart(), Target->getPageSize());
+  // Add the first PT_LOAD segment for regular output sections.
+  setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, getVAStart(), FileOff,
+          Target->getPageSize());
 
+  // Create phdrs as we assign VAs and file offsets to all output sections.
   SmallPtrSet<Elf_Phdr *, 8> Closed;
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
     if (Sec->getSize()) {
       uintX_t Flags = toPhdrFlags(Sec->getFlags());
-      Elf_Phdr *Last = &Phdrs.back();
+      Elf_Phdr *Last = &Phdrs[PhdrIdx];
       if (Last->p_flags != Flags || !needsPhdr<ELFT>(Sec)) {
         // Flags changed. End current Phdr and potentially create a new one.
         if (Closed.insert(Last).second) {
@@ -665,53 +646,59 @@ template <class ELFT> void Writer<ELFT>:
         if (needsPhdr<ELFT>(Sec)) {
           VA = RoundUpToAlignment(VA, Target->getPageSize());
           FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
-          Phdrs.emplace_back();
-          Elf_Phdr *PH = &Phdrs.back();
-          setPhdr(PH, PT_LOAD, Flags, FileOff, VA, Target->getPageSize());
+          Elf_Phdr *PH = &Phdrs[++PhdrIdx];
+          setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize());
         }
       }
     }
 
-    uintX_t Align = Sec->getAlign();
-    uintX_t Size = Sec->getSize();
     if (Sec->getFlags() & SHF_ALLOC) {
-      VA = RoundUpToAlignment(VA, Align);
+      VA = RoundUpToAlignment(VA, Sec->getAlign());
       Sec->setVA(VA);
-      VA += Size;
+      VA += Sec->getSize();
     }
-    FileOff = RoundUpToAlignment(FileOff, Align);
+    FileOff = RoundUpToAlignment(FileOff, Sec->getAlign());
     Sec->setFileOffset(FileOff);
     if (Sec->getType() != SHT_NOBITS)
-      FileOff += Size;
+      FileOff += Sec->getSize();
   }
 
-  if (Interp) {
-    Interp->p_type = PT_INTERP;
-    copyPhdr(Interp, Out<ELFT>::Interp);
-  }
+  // Add an entry for .dynamic.
   if (isOutputDynamic()) {
-    Phdrs.emplace_back();
-    Elf_Phdr *PH = &Phdrs.back();
+    Elf_Phdr *PH = &Phdrs[++PhdrIdx];
     PH->p_type = PT_DYNAMIC;
     copyPhdr(PH, Out<ELFT>::Dynamic);
   }
 
-  // Fix up the first entry's size.
-  PhdrPhdr->p_filesz = sizeof(Elf_Phdr) * Phdrs.size();
-  PhdrPhdr->p_memsz = sizeof(Elf_Phdr) * Phdrs.size();
-
-  // If nothing was merged into the file header PT_LOAD, set the size correctly.
-  if (FileHeader->p_filesz == Target->getPageSize()) {
-    uint64_t Size = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * Phdrs.size();
-    FileHeader->p_filesz = Size;
-    FileHeader->p_memsz = Size;
+  // Fix up PT_INTERP as we now know the address of .interp section.
+  if (Interp) {
+    Interp->p_type = PT_INTERP;
+    copyPhdr(Interp, Out<ELFT>::Interp);
   }
 
   // Add space for section headers.
-  FileOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
-  SectionHeaderOff = FileOff;
-  FileOff += getNumSections() * sizeof(Elf_Shdr);
-  FileSize = FileOff;
+  SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
+  FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
+}
+
+// Returns the number of PHDR entries.
+template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
+  int I = 2; // 2 for PT_PHDR and the first PT_LOAD
+  if (needsInterpSection())
+    ++I;
+  if (isOutputDynamic())
+    ++I;
+  uintX_t Last = PF_R;
+  for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+    if (!Sec->getSize() || !needsPhdr<ELFT>(Sec))
+      continue;
+    uintX_t Flags = toPhdrFlags(Sec->getFlags());
+    if (Last != Flags) {
+      Last = Flags;
+      ++I;
+    }
+  }
+  return I;
 }
 
 template <class ELFT> void Writer<ELFT>::writeHeader() {
@@ -786,12 +773,15 @@ template <class ELFT> void Writer<ELFT>:
 
 template <class ELFT>
 void Writer<ELFT>::setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags,
-                           uintX_t FileOff, uintX_t VA, uintX_t Align) {
+                           uintX_t FileOff, uintX_t VA, uintX_t Size,
+                           uintX_t Align) {
   PH->p_type = Type;
   PH->p_flags = Flags;
   PH->p_offset = FileOff;
   PH->p_vaddr = VA;
   PH->p_paddr = VA;
+  PH->p_filesz = Size;
+  PH->p_memsz = Size;
   PH->p_align = Align;
 }
 




More information about the llvm-commits mailing list