Simple ELF32/64 binary files can now be emitted for x86 and x86_64 without
relocation sections.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73038 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index 24f12a3..4bc2681 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -31,6 +31,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#define DEBUG_TYPE "elfwriter"
+
 #include "ELFWriter.h"
 #include "ELFCodeEmitter.h"
 #include "ELF.h"
@@ -48,6 +50,7 @@
 #include "llvm/Support/OutputBuffer.h"
 #include "llvm/Support/Streams.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
 #include <list>
 using namespace llvm;
 
@@ -67,13 +70,13 @@
 //===----------------------------------------------------------------------===//
 
 ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
-  : MachineFunctionPass(&ID), O(o), TM(tm) {
-  e_flags = 0;  // e_flags defaults to 0, no flags.
-  e_machine = TM.getELFWriterInfo()->getEMachine();
-
+  : MachineFunctionPass(&ID), O(o), TM(tm), ElfHdr() {
   is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
   isLittleEndian = TM.getTargetData()->isLittleEndian();
 
+  ElfHdr = new ELFHeader(TM.getELFWriterInfo()->getEMachine(), 0,
+                         is64Bit, isLittleEndian);
+
   // Create the machine code emitter object for this target.
   MCE = new ELFCodeEmitter(*this);
   NumSections = 0;
@@ -81,6 +84,7 @@
 
 ELFWriter::~ELFWriter() {
   delete MCE;
+  delete ElfHdr;
 }
 
 // doInitialization - Emit the file header and all of the global variables for
@@ -92,9 +96,6 @@
   std::vector<unsigned char> &FH = FileHeader;
   OutputBuffer FHOut(FH, is64Bit, isLittleEndian);
 
-  unsigned ElfClass = is64Bit ? ELFCLASS64 : ELFCLASS32;
-  unsigned ElfEndian = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
-
   // ELF Header
   // ----------
   // Fields e_shnum e_shstrndx are only known after all section have
@@ -111,26 +112,26 @@
   FHOut.outbyte('L');  // e_ident[EI_MAG2]
   FHOut.outbyte('F');  // e_ident[EI_MAG3]
 
-  FHOut.outbyte(ElfClass);   // e_ident[EI_CLASS]
-  FHOut.outbyte(ElfEndian);  // e_ident[EI_DATA]
-  FHOut.outbyte(EV_CURRENT); // e_ident[EI_VERSION]
+  FHOut.outbyte(ElfHdr->getElfClass());   // e_ident[EI_CLASS]
+  FHOut.outbyte(ElfHdr->getByteOrder());  // e_ident[EI_DATA]
+  FHOut.outbyte(EV_CURRENT);  // e_ident[EI_VERSION]
 
   FH.resize(16);  // e_ident[EI_NIDENT-EI_PAD]
 
-  FHOut.outhalf(ET_REL);     // e_type
-  FHOut.outhalf(e_machine);  // e_machine = target
-  FHOut.outword(EV_CURRENT); // e_version
-  FHOut.outaddr(0);          // e_entry = 0 -> no entry point in .o file
-  FHOut.outaddr(0);          // e_phoff = 0 -> no program header for .o
-
+  FHOut.outhalf(ET_REL);               // e_type
+  FHOut.outhalf(ElfHdr->getMachine()); // e_machine = target
+  FHOut.outword(EV_CURRENT);           // e_version
+  FHOut.outaddr(0);                    // e_entry = 0, no entry point in .o file
+  FHOut.outaddr(0);                    // e_phoff = 0, no program header for .o
   ELFHdr_e_shoff_Offset = FH.size();
-  FHOut.outaddr(0);                 // e_shoff = sec hdr table off in bytes
-  FHOut.outword(e_flags);           // e_flags = whatever the target wants
+  FHOut.outaddr(0);                    // e_shoff = sec hdr table off in bytes
+  FHOut.outword(ElfHdr->getFlags());   // e_flags = whatever the target wants
+  FHOut.outhalf(ElfHdr->getSize());    // e_ehsize = ELF header size
+  FHOut.outhalf(0);                    // e_phentsize = prog header entry size
+  FHOut.outhalf(0);                    // e_phnum = # prog header entries = 0
 
-  FHOut.outhalf(is64Bit ? 64 : 52); // e_ehsize = ELF header size
-  FHOut.outhalf(0);                 // e_phentsize = prog header entry size
-  FHOut.outhalf(0);                 // e_phnum     = # prog header entries = 0
-  FHOut.outhalf(is64Bit ? 64 : 40); // e_shentsize = sect hdr entry size
+  // e_shentsize = Section header entry size
+  FHOut.outhalf(ELFSection::getSectionHdrSize(is64Bit));
 
   // e_shnum     = # of section header ents
   ELFHdr_e_shnum_Offset = FH.size();
@@ -251,9 +252,10 @@
   // Emit the symbol table now, if non-empty.
   EmitSymbolTable();
 
-  // FIXME: Emit the relocations now.
+  // Emit the relocation sections.
+  EmitRelocations();
 
-  // Emit the string table for the sections in the ELF file we have.
+  // Emit the string table for the sections in the ELF file.
   EmitSectionTableStringTable();
 
   // Emit the sections to the .o file, and emit the section table for the file.
@@ -268,6 +270,10 @@
   return false;
 }
 
+/// EmitRelocations - Emit relocations
+void ELFWriter::EmitRelocations() {
+}
+
 /// EmitSymbolTable - If the current symbol table is non-empty, emit the string
 /// table for it and then the symbol table itself.
 void ELFWriter::EmitSymbolTable() {
@@ -284,7 +290,7 @@
 
   // Set the zero'th symbol to a null byte, as required.
   StrTabOut.outbyte(0);
-  SymbolTable[0].NameIdx = 0;
+  //SymbolTable[0].NameIdx = 0;
   unsigned Index = 1;
   for (unsigned i = 1, e = SymbolTable.size(); i != e; ++i) {
     // Use the name mangler to uniquify the LLVM symbol.
@@ -312,9 +318,9 @@
   // string table of each symbol, emit the symbol table itself.
   ELFSection &SymTab = getSection(".symtab", ELFSection::SHT_SYMTAB, 0);
   SymTab.Align = is64Bit ? 8 : 4;
-  SymTab.Link = SymTab.SectionIdx;     // Section Index of .strtab.
-  SymTab.Info = FirstNonLocalSymbol;   // First non-STB_LOCAL symbol.
-  SymTab.EntSize = 16; // Size of each symtab entry. FIXME: wrong for ELF64
+  SymTab.Link = StrTab.SectionIdx;      // Section Index of .strtab.
+  SymTab.Info = FirstNonLocalSymbol;    // First non-STB_LOCAL symbol.
+  SymTab.EntSize = is64Bit ? 24 : 16;   // Size of each symtab entry. 
   DataBuffer &SymTabBuf = SymTab.SectionData;
   OutputBuffer SymTabOut(SymTabBuf, is64Bit, isLittleEndian);
 
@@ -391,11 +397,21 @@
   // Emit all of the section data in order.
   for (std::list<ELFSection>::iterator I = SectionList.begin(),
          E = SectionList.end(); I != E; ++I) {
+
+    // Section idx 0 has 0 offset
+    if (!I->SectionIdx)
+      continue;
+
+    // Update Section size
+    if (!I->Size)
+      I->Size = I->SectionData.size();
+
     // Align FileOff to whatever the alignment restrictions of the section are.
     if (I->Align)
       FileOff = (FileOff+I->Align-1) & ~(I->Align-1);
+
     I->Offset = FileOff;
-    FileOff += I->SectionData.size();
+    FileOff += I->Size;
   }
 
   // Align Section Header.
@@ -429,19 +445,23 @@
       for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1);
            FileOff != NewFileOff; ++FileOff)
         O << (char)0xAB;
-    O.write((char*)&S.SectionData[0], S.SectionData.size());
-    FileOff += S.SectionData.size();
+    O.write((char*)&S.SectionData[0], S.Size);
+
+    DOUT << "SectionIdx: " << S.SectionIdx << ", Name: " << S.Name
+         << ", Size: " << S.Size << ", Offset: " << S.Offset << "\n";
+
+    FileOff += S.Size;
 
     TableOut.outword(S.NameIdx);  // sh_name - Symbol table name idx
     TableOut.outword(S.Type);     // sh_type - Section contents & semantics
-    TableOut.outword(S.Flags);    // sh_flags - Section flags.
+    TableOut.outaddr(S.Flags);    // sh_flags - Section flags.
     TableOut.outaddr(S.Addr);     // sh_addr - The mem addr this section is in.
     TableOut.outaddr(S.Offset);   // sh_offset - Offset from the file start.
-    TableOut.outword(S.Size);     // sh_size - The section size.
+    TableOut.outaddr(S.Size);     // sh_size - The section size.
     TableOut.outword(S.Link);     // sh_link - Section header table index link.
     TableOut.outword(S.Info);     // sh_info - Auxillary information.
-    TableOut.outword(S.Align);    // sh_addralign - Alignment of section.
-    TableOut.outword(S.EntSize);  // sh_entsize - Size of entries in the section
+    TableOut.outaddr(S.Align);    // sh_addralign - Alignment of section.
+    TableOut.outaddr(S.EntSize);  // sh_entsize - Size of entries in the section
 
     SectionList.pop_front();
   }