[ELF2] - Basic implementation of -r/--relocatable

-r, -relocatable - Generate relocatable output

Currently does not have support for files containing 
relocation sections with entries that refer to local 
symbols (like rel[a].eh_frame which refer to sections
and not to symbols)

Differential revision: http://reviews.llvm.org/D14382

llvm-svn: 261838
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 0fdffe9..d60d8ea 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -69,6 +69,7 @@
   void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
   void createPhdrs();
   void assignAddresses();
+  void assignAddressesRelocatable();
   void fixAbsoluteSymbols();
   bool openFile();
   void writeHeader();
@@ -93,13 +94,15 @@
   std::vector<std::unique_ptr<OutputSectionBase<ELFT>>> OwningSections;
 
   // We create a section for the ELF header and one for the program headers.
-  const unsigned NumDummySections = 2;
   ArrayRef<OutputSectionBase<ELFT> *> getSections() const {
-    return makeArrayRef(OutputSections).slice(NumDummySections);
+    return makeArrayRef(OutputSections).slice(dummySectionsNum());
   }
   unsigned getNumSections() const {
-    return OutputSections.size() + 1 - NumDummySections;
+    return OutputSections.size() + 1 - dummySectionsNum();
   }
+  // Usually there are 2 dummies sections: ELF header and program header.
+  // Relocatable output does not require program headers to be created.
+  unsigned dummySectionsNum() const { return Config->Relocatable ? 1 : 2; }
 
   void addRelIpltSymbols();
   void addStartEndSymbols();
@@ -193,8 +196,12 @@
   addReservedSymbols();
   if (!createSections())
     return;
-  createPhdrs();
-  assignAddresses();
+  if (!Config->Relocatable) {
+    createPhdrs();
+    assignAddresses();
+  } else {
+    assignAddressesRelocatable();
+  }
   fixAbsoluteSymbols();
   if (!openFile())
     return;
@@ -495,7 +502,7 @@
 
 template <class ELFT>
 static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {
-  if (Config->Shared && !Config->NoUndefined)
+  if ((Config->Relocatable || Config->Shared) && !Config->NoUndefined)
     return;
 
   std::string Msg = "undefined symbol: " + Sym->getName().str();
@@ -928,7 +935,8 @@
 // Create output section objects and add them to OutputSections.
 template <class ELFT> bool Writer<ELFT>::createSections() {
   OutputSections.push_back(Out<ELFT>::ElfHeader);
-  OutputSections.push_back(Out<ELFT>::ProgramHeaders);
+  if (!Config->Relocatable)
+    OutputSections.push_back(Out<ELFT>::ProgramHeaders);
 
   // Add .interp first because some loaders want to see that section
   // on the first page of the executable file when loaded into memory.
@@ -1040,8 +1048,8 @@
   std::stable_sort(OutputSections.begin(), OutputSections.end(),
                    compareSections<ELFT>);
 
-  for (unsigned I = NumDummySections, N = OutputSections.size(); I < N; ++I)
-    OutputSections[I]->SectionIndex = I + 1 - NumDummySections;
+  for (unsigned I = dummySectionsNum(), N = OutputSections.size(); I < N; ++I)
+    OutputSections[I]->SectionIndex = I + 1 - dummySectionsNum();
 
   for (OutputSectionBase<ELFT> *Sec : getSections())
     Sec->setSHName(Out<ELFT>::ShStrTab->addString(Sec->getName()));
@@ -1304,6 +1312,21 @@
     AddHdr(PT_GNU_STACK, PF_R | PF_W);
 }
 
+// Used for relocatable output (-r). In this case we create only ELF file
+// header, do not create program headers. Also assign of section addresses
+// is very straightforward: we just put all sections sequentually to the file.
+template <class ELFT> void Writer<ELFT>::assignAddressesRelocatable() {
+  Out<ELFT>::ElfHeader->setSize(sizeof(Elf_Ehdr));
+  uintX_t FileOff = 0;
+  for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+    FileOff = alignTo(FileOff, Sec->getAlign());
+    Sec->setFileOffset(FileOff);
+    FileOff += Sec->getSize();
+  }
+  SectionHeaderOff = alignTo(FileOff, sizeof(uintX_t));
+  FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
+}
+
 // Visits all headers in PhdrTable and assigns the adresses to
 // the output sections. Also creates common and special headers.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
@@ -1445,20 +1468,29 @@
   auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
   EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();
 
-  EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
+  if (Config->Shared)
+    EHdr->e_type = ET_DYN;
+  else if (Config->Relocatable)
+    EHdr->e_type = ET_REL;
+  else
+    EHdr->e_type = ET_EXEC;
+
   EHdr->e_machine = FirstObj.getEMachine();
   EHdr->e_version = EV_CURRENT;
   EHdr->e_entry = getEntryAddr<ELFT>();
-  EHdr->e_phoff = sizeof(Elf_Ehdr);
   EHdr->e_shoff = SectionHeaderOff;
   EHdr->e_flags = getELFFlags();
   EHdr->e_ehsize = sizeof(Elf_Ehdr);
-  EHdr->e_phentsize = sizeof(Elf_Phdr);
   EHdr->e_phnum = Phdrs.size();
   EHdr->e_shentsize = sizeof(Elf_Shdr);
   EHdr->e_shnum = getNumSections();
   EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;
 
+  if (!Config->Relocatable) {
+    EHdr->e_phoff = sizeof(Elf_Ehdr);
+    EHdr->e_phentsize = sizeof(Elf_Phdr);
+  }
+
   // Write the program header table.
   auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
   for (Phdr &P : Phdrs)