From 83ed6b781470e7ef34c22d772422f5de92512be9 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 14 Apr 2015 22:54:16 +0000 Subject: [PATCH] Use the ability to pwrite to simplify the ELF writer. Now we don't have to do 2 synchronized passes to compute offsets and then write the file. This also includes a fix for the corner case of seeking in /dev/null. It is not an error, but on some systems (Linux) the returned offset is always 0. An error is signaled by returning -1. This is checked by the existing tests now that "clang -o /dev/null ..." seeks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@234952 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/ELFObjectWriter.cpp | 75 +++++++++++++++---------------------- lib/Support/raw_ostream.cpp | 2 +- 2 files changed, 32 insertions(+), 45 deletions(-) diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 2b8b8ba98d7..583f2fd15a5 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -92,14 +92,11 @@ class ELFObjectWriter : public MCObjectWriter { static bool isLocal(const MCSymbolData &Data, bool isUsedInReloc); static bool IsELFMetaDataSection(const MCSectionData &SD); static uint64_t DataSectionSize(const MCSectionData &SD); - static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, - const MCSectionData &SD); static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout, const MCSectionData &SD); - void WriteDataSectionData(MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCSectionELF &Section); + void writeDataSectionData(MCAssembler &Asm, const MCAsmLayout &Layout, + const MCSectionData &SD); /// Helper struct for containing some precomputed information on symbols. struct ELFSymbolData { @@ -201,7 +198,6 @@ class ELFObjectWriter : public MCObjectWriter { } void WriteHeader(const MCAssembler &Asm, - uint64_t SectionHeaderOffset, unsigned NumberOfSections); void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, @@ -409,7 +405,6 @@ ELFObjectWriter::~ELFObjectWriter() // Emit the ELF header. void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, - uint64_t SectionHeaderOffset, unsigned NumberOfSections) { // ELF Header // ---------- @@ -443,7 +438,7 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, Write32(ELF::EV_CURRENT); // e_version WriteWord(0); // e_entry, no entry point in .o file WriteWord(0); // e_phoff, no program header for .o - WriteWord(SectionHeaderOffset); // e_shoff = sec hdr table off in bytes + WriteWord(0); // e_shoff = sec hdr table off in bytes // e_flags = whatever the target wants Write32(Asm.getELFHeaderEFlags()); @@ -1532,13 +1527,6 @@ uint64_t ELFObjectWriter::DataSectionSize(const MCSectionData &SD) { return Ret; } -uint64_t ELFObjectWriter::GetSectionFileSize(const MCAsmLayout &Layout, - const MCSectionData &SD) { - if (IsELFMetaDataSection(SD)) - return DataSectionSize(SD); - return Layout.getSectionFileSize(&SD); -} - uint64_t ELFObjectWriter::GetSectionAddressSize(const MCAsmLayout &Layout, const MCSectionData &SD) { if (IsELFMetaDataSection(SD)) @@ -1546,14 +1534,9 @@ uint64_t ELFObjectWriter::GetSectionAddressSize(const MCAsmLayout &Layout, return Layout.getSectionAddressSize(&SD); } -void ELFObjectWriter::WriteDataSectionData(MCAssembler &Asm, +void ELFObjectWriter::writeDataSectionData(MCAssembler &Asm, const MCAsmLayout &Layout, - const MCSectionELF &Section) { - const MCSectionData &SD = Asm.getOrCreateSectionData(Section); - - uint64_t Padding = OffsetToAlignment(OS.tell(), SD.getAlignment()); - WriteZeros(Padding); - + const MCSectionData &SD) { if (IsELFMetaDataSection(SD)) { for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; ++i) { @@ -1655,45 +1638,49 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, const_cast(Layout), SectionIndexMap); - uint64_t NaturalAlignment = is64Bit() ? 8 : 4; - uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) : - sizeof(ELF::Elf32_Ehdr); - uint64_t FileOff = HeaderSize; - std::vector Sections; ComputeSectionOrder(Asm, Sections); unsigned NumSections = Sections.size(); SectionOffsetMapTy SectionOffsetMap; - for (unsigned i = 0; i < NumSections; ++i) { + // Write out the ELF header ... + WriteHeader(Asm, NumSections + 1); + + // ... then the sections ... + for (unsigned i = 0; i < NumSections; ++i) { const MCSectionELF &Section = *Sections[i]; const MCSectionData &SD = Asm.getOrCreateSectionData(Section); - - FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); + uint64_t Padding = OffsetToAlignment(OS.tell(), SD.getAlignment()); + WriteZeros(Padding); // Remember the offset into the file for this section. - SectionOffsetMap[&Section] = FileOff; + SectionOffsetMap[&Section] = OS.tell(); - // Get the size of the section in the output file (including padding). - FileOff += GetSectionFileSize(Layout, SD); + writeDataSectionData(Asm, Layout, SD); } - FileOff = RoundUpToAlignment(FileOff, NaturalAlignment); - - const unsigned SectionHeaderOffset = FileOff; - - // Write out the ELF header ... - WriteHeader(Asm, SectionHeaderOffset, NumSections + 1); - - // ... then the sections ... - for (unsigned i = 0; i < NumSections; ++i) - WriteDataSectionData(Asm, Layout, *Sections[i]); - + uint64_t NaturalAlignment = is64Bit() ? 8 : 4; uint64_t Padding = OffsetToAlignment(OS.tell(), NaturalAlignment); WriteZeros(Padding); + const unsigned SectionHeaderOffset = OS.tell(); + // ... then the section header table ... writeSectionHeader(Asm, GroupMap, Layout, SectionIndexMap, SectionOffsetMap); + + if (is64Bit()) { + uint64_t Val = SectionHeaderOffset; + if (sys::IsLittleEndianHost != IsLittleEndian) + sys::swapByteOrder(Val); + OS.pwrite(reinterpret_cast(&Val), sizeof(Val), + offsetof(ELF::Elf64_Ehdr, e_shoff)); + } else { + uint32_t Val = SectionHeaderOffset; + if (sys::IsLittleEndianHost != IsLittleEndian) + sys::swapByteOrder(Val); + OS.pwrite(reinterpret_cast(&Val), sizeof(Val), + offsetof(ELF::Elf32_Ehdr, e_shoff)); + } } bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index 044f8e0ca86..6f9f910cad9 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -625,7 +625,7 @@ void raw_fd_ostream::close() { uint64_t raw_fd_ostream::seek(uint64_t off) { flush(); pos = ::lseek(FD, off, SEEK_SET); - if (pos != off) + if (pos == (uint64_t)-1) error_detected(); return pos; } -- 2.34.1