Use pwrite to write the number of sections.
[oota-llvm.git] / lib / MC / ELFObjectWriter.cpp
index 185b66332be9e7da064081de50fd81e59eca2606..e0214b476c3d73a03e83411820733da66c870046 100644 (file)
@@ -194,8 +194,7 @@ class ELFObjectWriter : public MCObjectWriter {
       FWriter.write(F, Value);
     }
 
-    void WriteHeader(const MCAssembler &Asm,
-                     unsigned NumberOfSections);
+    void writeHeader(const MCAssembler &Asm);
 
     void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD,
                      const MCAsmLayout &Layout);
@@ -217,8 +216,8 @@ class ELFObjectWriter : public MCObjectWriter {
     uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm,
                                          const MCSymbol *S);
 
-    // Map from a signature symbol to the group section
-    typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy;
+    // Map from a signature symbol to the group section index
+    typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy;
     // Start and end offset of each section
     typedef std::vector<std::pair<uint64_t, uint64_t>> SectionOffsetsTy;
 
@@ -231,7 +230,9 @@ class ELFObjectWriter : public MCObjectWriter {
                             const SectionIndexMapTy &SectionIndexMap,
                             const RevGroupMapTy &RevGroupMap);
 
-    void maybeAddToGroup(MCAssembler &Asm, const RevGroupMapTy &RevGroupMap,
+    void maybeAddToGroup(MCAssembler &Asm,
+                         ArrayRef<const MCSectionELF *> Sections,
+                         const RevGroupMapTy &RevGroupMap,
                          const MCSectionELF &Section, unsigned Index);
 
     void computeIndexMap(MCAssembler &Asm,
@@ -239,19 +240,23 @@ class ELFObjectWriter : public MCObjectWriter {
                          SectionIndexMapTy &SectionIndexMap,
                          const RevGroupMapTy &RevGroupMap);
 
-    MCSectionData *createRelocationSection(MCAssembler &Asm,
-                                           const MCSectionData &SD);
+    void createRelocationSection(MCAssembler &Asm, const MCSectionData &SD);
 
     void CompressDebugSections(MCAssembler &Asm, MCAsmLayout &Layout);
 
-    void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout);
+    void WriteRelocations(MCAssembler &Asm, const MCAsmLayout &Layout);
 
-    void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout,
+    void
+    createSectionHeaderStringTable(MCAssembler &Asm,
+                                   std::vector<const MCSectionELF *> &Sections);
+    void createStringTable(MCAssembler &Asm,
+                           std::vector<const MCSectionELF *> &Sections);
+    void CreateMetadataSections(MCAssembler &Asm, const MCAsmLayout &Layout,
                                 std::vector<const MCSectionELF *> &Sections);
 
     // Create the sections that show up in the symbol table. Currently
     // those are the .note.GNU-stack section and the group sections.
-    void createIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout,
+    void createIndexedSections(MCAssembler &Asm, const MCAsmLayout &Layout,
                                RevGroupMapTy &RevGroupMap,
                                std::vector<const MCSectionELF *> &Sections,
                                SectionIndexMapTy &SectionIndexMap);
@@ -399,8 +404,7 @@ ELFObjectWriter::~ELFObjectWriter()
 {}
 
 // Emit the ELF header.
-void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
-                                  unsigned NumberOfSections) {
+void ELFObjectWriter::writeHeader(const MCAssembler &Asm) {
   // ELF Header
   // ----------
   //
@@ -445,16 +449,11 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
   Write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
 
   // e_shnum     = # of section header ents
-  if (NumberOfSections >= ELF::SHN_LORESERVE)
-    Write16(ELF::SHN_UNDEF);
-  else
-    Write16(NumberOfSections);
+  Write16(0);
 
   // e_shstrndx  = Section # of '.shstrtab'
-  if (ShstrtabIndex >= ELF::SHN_LORESERVE)
-    Write16(ELF::SHN_XINDEX);
-  else
-    Write16(ShstrtabIndex);
+  assert(ShstrtabIndex < ELF::SHN_LORESERVE);
+  Write16(ShstrtabIndex);
 }
 
 uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,
@@ -941,13 +940,14 @@ bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isUsedInReloc) {
 }
 
 void ELFObjectWriter::maybeAddToGroup(MCAssembler &Asm,
+                                      ArrayRef<const MCSectionELF *> Sections,
                                       const RevGroupMapTy &RevGroupMap,
                                       const MCSectionELF &Section,
                                       unsigned Index) {
   const MCSymbol *Sym = Section.getGroup();
   if (!Sym)
     return;
-  const MCSectionELF *Group = RevGroupMap.lookup(Sym);
+  const MCSectionELF *Group = Sections[RevGroupMap.lookup(Sym) - 1];
   MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
   // FIXME: we could use the previous fragment
   MCDataFragment *F = new MCDataFragment(&Data);
@@ -957,32 +957,16 @@ void ELFObjectWriter::maybeAddToGroup(MCAssembler &Asm,
 void ELFObjectWriter::computeIndexMap(
     MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections,
     SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap) {
-  std::vector<const MCSectionELF *> RelSections;
   for (const MCSectionData &SD : Asm) {
     const MCSectionELF &Section =
       static_cast<const MCSectionELF &>(SD.getSection());
-    if (Section.getType() == ELF::SHT_GROUP ||
-        Section.getType() == ELF::SHT_REL ||
-        Section.getType() == ELF::SHT_RELA)
+    if (Section.getType() == ELF::SHT_GROUP)
       continue;
     Sections.push_back(&Section);
     unsigned Index = Sections.size();
     SectionIndexMap[&Section] = Index;
-    maybeAddToGroup(Asm, RevGroupMap, Section, Index);
-
-    if (MCSectionData *RelSD = createRelocationSection(Asm, SD)) {
-      const MCSectionELF *RelSection =
-          static_cast<const MCSectionELF *>(&RelSD->getSection());
-      RelSections.push_back(RelSection);
-    }
-  }
-
-  // Put relocation sections close together. The linker reads them
-  // first, so this improves cache locality.
-  for (const MCSectionELF *Sec : RelSections) {
-    Sections.push_back(Sec);
-    unsigned Index = Sections.size();
-    maybeAddToGroup(Asm, RevGroupMap, *Sec, Index);
+    maybeAddToGroup(Asm, Sections, RevGroupMap, Section, Index);
+    createRelocationSection(Asm, SD);
   }
 }
 
@@ -1034,7 +1018,7 @@ void ELFObjectWriter::computeSymbolTable(
       MSD.SectionIndex = ELF::SHN_COMMON;
     } else if (BaseSymbol->isUndefined()) {
       if (isSignature && !Used)
-        MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap.lookup(&Symbol));
+        MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
       else
         MSD.SectionIndex = ELF::SHN_UNDEF;
       if (!Used && WeakrefUsed)
@@ -1131,11 +1115,10 @@ void ELFObjectWriter::computeSymbolTable(
     UndefinedSymbolData[i].SymbolData->setIndex(Index++);
 }
 
-MCSectionData *
-ELFObjectWriter::createRelocationSection(MCAssembler &Asm,
-                                         const MCSectionData &SD) {
+void ELFObjectWriter::createRelocationSection(MCAssembler &Asm,
+                                              const MCSectionData &SD) {
   if (Relocations[&SD].empty())
-    return nullptr;
+    return;
 
   MCContext &Ctx = Asm.getContext();
   const MCSectionELF &Section =
@@ -1158,11 +1141,11 @@ ELFObjectWriter::createRelocationSection(MCAssembler &Asm,
   const MCSectionELF *RelaSection = Ctx.createELFRelSection(
       RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
       Flags, EntrySize, Section.getGroup(), &Section);
-  return &Asm.getOrCreateSectionData(*RelaSection);
+  Asm.getOrCreateSectionData(*RelaSection);
 }
 
 static SmallVector<char, 128>
-getUncompressedData(MCAsmLayout &Layout,
+getUncompressedData(const MCAsmLayout &Layout,
                     MCSectionData::FragmentListType &Fragments) {
   SmallVector<char, 128> UncompressedData;
   for (const MCFragment &F : Fragments) {
@@ -1209,7 +1192,7 @@ prependCompressionHeader(uint64_t Size,
 // Return a single fragment containing the compressed contents of the whole
 // section. Null if the section was not compressed for any reason.
 static std::unique_ptr<MCDataFragment>
-getCompressedFragment(MCAsmLayout &Layout,
+getCompressedFragment(const MCAsmLayout &Layout,
                       MCSectionData::FragmentListType &Fragments) {
   std::unique_ptr<MCDataFragment> CompressedFragment(new MCDataFragment());
 
@@ -1306,7 +1289,8 @@ void ELFObjectWriter::CompressDebugSections(MCAssembler &Asm,
   }
 }
 
-void ELFObjectWriter::WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) {
+void ELFObjectWriter::WriteRelocations(MCAssembler &Asm,
+                                       const MCAsmLayout &Layout) {
   for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
     MCSectionData &RelSD = *it;
     const MCSectionELF &RelSection =
@@ -1386,22 +1370,41 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
   }
 }
 
+void ELFObjectWriter::createSectionHeaderStringTable(
+    MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections) {
+  const MCSectionELF *ShstrtabSection = Sections[ShstrtabIndex - 1];
+
+  Asm.getOrCreateSectionData(*ShstrtabSection);
+
+  for (MCSectionData &SD : Asm) {
+    const MCSectionELF &Section =
+        static_cast<const MCSectionELF &>(SD.getSection());
+    ShStrTabBuilder.add(Section.getSectionName());
+  }
+  ShStrTabBuilder.finalize(StringTableBuilder::ELF);
+  OS << ShStrTabBuilder.data();
+}
+
+void ELFObjectWriter::createStringTable(
+    MCAssembler &Asm, std::vector<const MCSectionELF *> &Sections) {
+  MCContext &Ctx = Asm.getContext();
+  const MCSectionELF *StrtabSection =
+      Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
+  Asm.getOrCreateSectionData(*StrtabSection);
+  Sections.push_back(StrtabSection);
+  StringTableIndex = Sections.size();
+  OS << StrTabBuilder.data();
+}
+
 void ELFObjectWriter::CreateMetadataSections(
-    MCAssembler &Asm, MCAsmLayout &Layout,
+    MCAssembler &Asm, const MCAsmLayout &Layout,
     std::vector<const MCSectionELF *> &Sections) {
   MCContext &Ctx = Asm.getContext();
   MCDataFragment *F;
 
   unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
 
-  // We construct .shstrtab, .symtab and .strtab in this order to match gnu as.
-  const MCSectionELF *ShstrtabSection =
-      Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0);
-  MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection);
-  ShstrtabSD.setAlignment(1);
-  ShstrtabIndex = Sections.size() + 1;
-  Sections.push_back(ShstrtabSection);
-
+  // Symbol table
   const MCSectionELF *SymtabSection =
     Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
                       EntrySize, "");
@@ -1409,41 +1412,22 @@ void ELFObjectWriter::CreateMetadataSections(
   SymtabSD.setAlignment(is64Bit() ? 8 : 4);
   SymbolTableIndex = Sections.size() + 1;
   Sections.push_back(SymtabSection);
-
-  const MCSectionELF *StrtabSection;
-  StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
-  MCSectionData &StrtabSD = Asm.getOrCreateSectionData(*StrtabSection);
-  StrtabSD.setAlignment(1);
-  StringTableIndex = Sections.size() + 1;
-  Sections.push_back(StrtabSection);
-
-  // Symbol table
   F = new MCDataFragment(&SymtabSD);
   WriteSymbolTable(F, Asm, Layout, Sections);
-
-  F = new MCDataFragment(&StrtabSD);
-  F->getContents().append(StrTabBuilder.data().begin(),
-                          StrTabBuilder.data().end());
-
-  F = new MCDataFragment(&ShstrtabSD);
-
-  // Section header string table.
-  for (auto it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
-    const MCSectionELF &Section =
-      static_cast<const MCSectionELF&>(it->getSection());
-    ShStrTabBuilder.add(Section.getSectionName());
-  }
-  ShStrTabBuilder.finalize(StringTableBuilder::ELF);
-  F->getContents().append(ShStrTabBuilder.data().begin(),
-                          ShStrTabBuilder.data().end());
 }
 
 void ELFObjectWriter::createIndexedSections(
-    MCAssembler &Asm, MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap,
+    MCAssembler &Asm, const MCAsmLayout &Layout, RevGroupMapTy &RevGroupMap,
     std::vector<const MCSectionELF *> &Sections,
     SectionIndexMapTy &SectionIndexMap) {
   MCContext &Ctx = Asm.getContext();
 
+  const MCSectionELF *ShstrtabSection =
+      Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0);
+  Sections.push_back(ShstrtabSection);
+  ShstrtabIndex = Sections.size();
+  assert(ShstrtabIndex == 1);
+
   // Build the groups
   for (const MCSectionData &SD : Asm) {
     const MCSectionELF &Section =
@@ -1453,11 +1437,11 @@ void ELFObjectWriter::createIndexedSections(
 
     const MCSymbol *SignatureSymbol = Section.getGroup();
     Asm.getOrCreateSymbolData(*SignatureSymbol);
-    const MCSectionELF *&Group = RevGroupMap[SignatureSymbol];
-    if (!Group) {
-      Group = Ctx.createELFGroupSection(SignatureSymbol);
+    unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
+    if (!GroupIdx) {
+      const MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
       Sections.push_back(Group);
-      SectionIndexMap[Group] = Sections.size();
+      GroupIdx = Sections.size();
 
       MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
       Data.setAlignment(4);
@@ -1551,9 +1535,7 @@ void ELFObjectWriter::writeSectionHeader(
   // Null section first.
   uint64_t FirstSectionSize =
       (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;
-  uint32_t FirstSectionLink =
-    ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0;
-  WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0);
+  WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0);
 
   for (unsigned i = 0; i < NumSections; ++i) {
     const MCSectionELF &Section = *Sections[i];
@@ -1581,26 +1563,24 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
 
   CompressDebugSections(Asm, const_cast<MCAsmLayout &>(Layout));
   std::vector<const MCSectionELF *> Sections;
-  createIndexedSections(Asm, const_cast<MCAsmLayout &>(Layout), RevGroupMap,
-                        Sections, SectionIndexMap);
+  createIndexedSections(Asm, Layout, RevGroupMap, Sections, SectionIndexMap);
 
   // Compute symbol table information.
   computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap);
 
-  WriteRelocations(Asm, const_cast<MCAsmLayout &>(Layout));
+  WriteRelocations(Asm, Layout);
 
-  CreateMetadataSections(const_cast<MCAssembler &>(Asm),
-                         const_cast<MCAsmLayout &>(Layout), Sections);
+  CreateMetadataSections(Asm, Layout, Sections);
 
-  unsigned NumSections = Asm.size();
   SectionOffsetsTy SectionOffsets;
 
   // Write out the ELF header ...
-  WriteHeader(Asm, NumSections + 1);
+  writeHeader(Asm);
 
   // ... then the sections ...
-  for (const MCSectionELF *Section : Sections) {
-    const MCSectionData &SD = Asm.getOrCreateSectionData(*Section);
+  SectionOffsets.push_back(std::make_pair(0, 0));
+  for (auto I = ++Sections.begin(), E = Sections.end(); I != E; ++I) {
+    const MCSectionData &SD = Asm.getOrCreateSectionData(**I);
     uint64_t Padding = OffsetToAlignment(OS.tell(), SD.getAlignment());
     WriteZeros(Padding);
 
@@ -1611,6 +1591,20 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
     SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
   }
 
+  {
+    uint64_t SecStart = OS.tell();
+    createStringTable(Asm, Sections);
+    uint64_t SecEnd = OS.tell();
+    SectionOffsets.push_back(std::make_pair(SecStart, SecEnd));
+  }
+
+  {
+    uint64_t SecStart = OS.tell();
+    createSectionHeaderStringTable(Asm, Sections);
+    uint64_t SecEnd = OS.tell();
+    SectionOffsets[0] = std::make_pair(SecStart, SecEnd);
+  }
+
   uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
   uint64_t Padding = OffsetToAlignment(OS.tell(), NaturalAlignment);
   WriteZeros(Padding);
@@ -1620,19 +1614,30 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
   // ... then the section header table ...
   writeSectionHeader(Sections, Asm, Layout, SectionIndexMap, SectionOffsets);
 
+  uint16_t NumSections = (Sections.size() + 1 >= ELF::SHN_LORESERVE)
+                             ? ELF::SHN_UNDEF
+                             : Sections.size() + 1;
+  if (sys::IsLittleEndianHost != IsLittleEndian)
+    sys::swapByteOrder(NumSections);
+  unsigned NumSectionsOffset;
+
   if (is64Bit()) {
     uint64_t Val = SectionHeaderOffset;
     if (sys::IsLittleEndianHost != IsLittleEndian)
       sys::swapByteOrder(Val);
     OS.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
               offsetof(ELF::Elf64_Ehdr, e_shoff));
+    NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
   } else {
     uint32_t Val = SectionHeaderOffset;
     if (sys::IsLittleEndianHost != IsLittleEndian)
       sys::swapByteOrder(Val);
     OS.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
               offsetof(ELF::Elf32_Ehdr, e_shoff));
+    NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
   }
+  OS.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
+            NumSectionsOffset);
 }
 
 bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(