From 5f53af361710c51a1272523cef17b51f4f8fcb15 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 2 Aug 2017 00:03:33 +0000 Subject: [PATCH] Revert "Reland "[llvm][llvm-objcopy] Added support for outputting to binary in llvm-objcopy"" This is failing to compile on 32-bit ARM bots. This reverts commit r309768. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309771 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tools/llvm-objcopy/basic-align-copy.test | 37 ---- .../tools/llvm-objcopy/basic-binary-copy.test | 25 --- tools/llvm-objcopy/LLVMBuild.txt | 2 +- tools/llvm-objcopy/Object.cpp | 204 +++++++----------- tools/llvm-objcopy/Object.h | 55 +---- tools/llvm-objcopy/llvm-objcopy.cpp | 18 +- 6 files changed, 88 insertions(+), 253 deletions(-) delete mode 100644 test/tools/llvm-objcopy/basic-align-copy.test delete mode 100644 test/tools/llvm-objcopy/basic-binary-copy.test diff --git a/test/tools/llvm-objcopy/basic-align-copy.test b/test/tools/llvm-objcopy/basic-align-copy.test deleted file mode 100644 index f47f7097c79..00000000000 --- a/test/tools/llvm-objcopy/basic-align-copy.test +++ /dev/null @@ -1,37 +0,0 @@ -# RUN: yaml2obj %s -o %t -# RUN: llvm-objcopy -O binary %t %t2 -# RUN: od -t x2 %t2 | FileCheck %s -# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE - -!ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_EXEC - Machine: EM_X86_64 -Sections: - - Name: .text - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - AddressAlign: 0x0000000000001000 - Content: "c3c3c3c3" - - Name: .data - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - AddressAlign: 0x0000000000001000 - Content: "32" -ProgramHeaders: - - Type: PT_LOAD - Flags: [ PF_X, PF_R ] - Sections: - - Section: .text - - Type: PT_LOAD - Flags: [ PF_R ] - Sections: - - Section: .data - -# CHECK: 0000000 c3c3 c3c3 0000 0000 0000 0000 0000 0000 -# CHECK-NEXT: 0000020 0000 0000 0000 0000 0000 0000 0000 0000 -# CHECK-NEXT: * -# CHECK-NEXT: 0010000 0032 -# SIZE: 4097 diff --git a/test/tools/llvm-objcopy/basic-binary-copy.test b/test/tools/llvm-objcopy/basic-binary-copy.test deleted file mode 100644 index 5808f1aadf3..00000000000 --- a/test/tools/llvm-objcopy/basic-binary-copy.test +++ /dev/null @@ -1,25 +0,0 @@ -# RUN: yaml2obj %s -o %t -# RUN: llvm-objcopy -O binary %t %t2 -# RUN: od -t x2 -v %t2 | FileCheck %s -# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE - -!ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_EXEC - Machine: EM_X86_64 -Sections: - - Name: .text - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - AddressAlign: 0x0000000000001000 - Content: "c3c3c3c3" -ProgramHeaders: - - Type: PT_LOAD - Flags: [ PF_X, PF_R ] - Sections: - - Section: .text - -# CHECK: 0000000 c3c3 c3c3 -# SIZE: 4 diff --git a/tools/llvm-objcopy/LLVMBuild.txt b/tools/llvm-objcopy/LLVMBuild.txt index 0a3473a222b..4a75d525876 100644 --- a/tools/llvm-objcopy/LLVMBuild.txt +++ b/tools/llvm-objcopy/LLVMBuild.txt @@ -18,4 +18,4 @@ type = Tool name = llvm-objcopy parent = Tools -required_libraries = Object Support MC +required_libraries = Object MC diff --git a/tools/llvm-objcopy/Object.cpp b/tools/llvm-objcopy/Object.cpp index cf55212aefd..77ac8d913de 100644 --- a/tools/llvm-objcopy/Object.cpp +++ b/tools/llvm-objcopy/Object.cpp @@ -42,13 +42,6 @@ void Segment::finalize() { } } -void Segment::writeSegment(FileOutputBuffer &Out) const { - uint8_t *Buf = Out.getBufferStart() + Offset; - // We want to maintain segments' interstitial data and contents exactly. - // This lets us just copy segments directly. - std::copy(std::begin(Contents), std::end(Contents), Buf); -} - void SectionBase::finalize() {} template @@ -106,8 +99,7 @@ template void Object::readProgramHeaders(const ELFFile &ElfFile) { uint32_t Index = 0; for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) { - ArrayRef Data{ElfFile.base() + Phdr.p_offset, Phdr.p_filesz}; - Segments.emplace_back(llvm::make_unique(Data)); + Segments.emplace_back(llvm::make_unique()); Segment &Seg = *Segments.back(); Seg.Type = Phdr.p_type; Seg.Flags = Phdr.p_flags; @@ -143,7 +135,7 @@ Object::makeSection(const llvm::object::ELFFile &ElfFile, default: Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); return llvm::make_unique
(Data); - } + }; } template @@ -171,6 +163,12 @@ void Object::readSectionHeaders(const ELFFile &ElfFile) { } } +template size_t Object::totalSize() const { + // We already have the section header offset so we can calculate the total + // size by just adding up the size of each section header. + return SHOffset + Sections.size() * sizeof(Elf_Shdr) + sizeof(Elf_Shdr); +} + template Object::Object(const ELFObjectFile &Obj) { const auto &ElfFile = *Obj.getELFFile(); const auto &Ehdr = *ElfFile.getHeader(); @@ -189,76 +187,22 @@ template Object::Object(const ELFObjectFile &Obj) { dyn_cast(Sections[Ehdr.e_shstrndx - 1].get()); } -template -void Object::writeHeader(FileOutputBuffer &Out) const { - uint8_t *Buf = Out.getBufferStart(); - Elf_Ehdr &Ehdr = *reinterpret_cast(Buf); - std::copy(Ident, Ident + 16, Ehdr.e_ident); - Ehdr.e_type = Type; - Ehdr.e_machine = Machine; - Ehdr.e_version = Version; - Ehdr.e_entry = Entry; - Ehdr.e_phoff = sizeof(Elf_Ehdr); - Ehdr.e_shoff = SHOffset; - Ehdr.e_flags = Flags; - Ehdr.e_ehsize = sizeof(Elf_Ehdr); - Ehdr.e_phentsize = sizeof(Elf_Phdr); - Ehdr.e_phnum = Segments.size(); - Ehdr.e_shentsize = sizeof(Elf_Shdr); - Ehdr.e_shnum = Sections.size() + 1; - Ehdr.e_shstrndx = SectionNames->Index; -} - -template -void Object::writeProgramHeaders(FileOutputBuffer &Out) const { - for (auto &Phdr : Segments) - Phdr->template writeHeader(Out); -} - -template -void Object::writeSectionHeaders(FileOutputBuffer &Out) const { - uint8_t *Buf = Out.getBufferStart() + SHOffset; - // This reference serves to write the dummy section header at the begining - // of the file. - Elf_Shdr &Shdr = *reinterpret_cast(Buf); - Shdr.sh_name = 0; - Shdr.sh_type = SHT_NULL; - Shdr.sh_flags = 0; - Shdr.sh_addr = 0; - Shdr.sh_offset = 0; - Shdr.sh_size = 0; - Shdr.sh_link = 0; - Shdr.sh_info = 0; - Shdr.sh_addralign = 0; - Shdr.sh_entsize = 0; - - for (auto &Section : Sections) - Section->template writeHeader(Out); -} - -template -void Object::writeSectionData(FileOutputBuffer &Out) const { - for (auto &Section : Sections) - Section->writeSection(Out); -} - -template void ELFObject::sortSections() { +template void Object::sortSections() { // Put all sections in offset order. Maintain the ordering as closely as // possible while meeting that demand however. auto CompareSections = [](const SecPtr &A, const SecPtr &B) { return A->OriginalOffset < B->OriginalOffset; }; - std::stable_sort(std::begin(this->Sections), std::end(this->Sections), - CompareSections); + std::stable_sort(std::begin(Sections), std::end(Sections), CompareSections); } -template void ELFObject::assignOffsets() { +template void Object::assignOffsets() { // Decide file offsets and indexes. - size_t PhdrSize = this->Segments.size() * sizeof(Elf_Phdr); + size_t PhdrSize = Segments.size() * sizeof(Elf_Phdr); // We can put section data after the ELF header and the program headers. uint64_t Offset = sizeof(Elf_Ehdr) + PhdrSize; uint64_t Index = 1; - for (auto &Section : this->Sections) { + for (auto &Section : Sections) { // The segment can have a different alignment than the section. In the case // that there is a parent segment then as long as we satisfy the alignment // of the segment it should follow that that the section is aligned. @@ -305,93 +249,93 @@ template void ELFObject::assignOffsets() { // this needs to be 4-byte aligned and on 64-bit it needs to be 8-byte aligned // so the size of ELFT::Addr is used to ensure this. Offset = alignTo(Offset, sizeof(typename ELFT::Addr)); - this->SHOffset = Offset; + SHOffset = Offset; } -template size_t ELFObject::totalSize() const { - // We already have the section header offset so we can calculate the total - // size by just adding up the size of each section header. - return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr) + - sizeof(Elf_Shdr); -} - -template void ELFObject::write(FileOutputBuffer &Out) const { - this->writeHeader(Out); - this->writeProgramHeaders(Out); - this->writeSectionData(Out); - this->writeSectionHeaders(Out); -} - -template void ELFObject::finalize() { - for (const auto &Section : this->Sections) { - this->SectionNames->addString(Section->Name); - } +template void Object::finalize() { + for (auto &Section : Sections) + SectionNames->addString(Section->Name); sortSections(); assignOffsets(); // Finalize SectionNames first so that we can assign name indexes. - this->SectionNames->finalize(); + SectionNames->finalize(); // Finally now that all offsets and indexes have been set we can finalize any // remaining issues. - uint64_t Offset = this->SHOffset + sizeof(Elf_Shdr); - for (auto &Section : this->Sections) { + uint64_t Offset = SHOffset + sizeof(Elf_Shdr); + for (auto &Section : Sections) { Section->HeaderOffset = Offset; Offset += sizeof(Elf_Shdr); - Section->NameIndex = this->SectionNames->findIndex(Section->Name); + Section->NameIndex = SectionNames->findIndex(Section->Name); Section->finalize(); } - for (auto &Segment : this->Segments) + for (auto &Segment : Segments) Segment->finalize(); } -template size_t BinaryObject::totalSize() const { - return TotalSize; +template +void Object::writeHeader(FileOutputBuffer &Out) const { + uint8_t *Buf = Out.getBufferStart(); + Elf_Ehdr &Ehdr = *reinterpret_cast(Buf); + std::copy(Ident, Ident + 16, Ehdr.e_ident); + Ehdr.e_type = Type; + Ehdr.e_machine = Machine; + Ehdr.e_version = Version; + Ehdr.e_entry = Entry; + Ehdr.e_phoff = sizeof(Elf_Ehdr); + Ehdr.e_shoff = SHOffset; + Ehdr.e_flags = Flags; + Ehdr.e_ehsize = sizeof(Elf_Ehdr); + Ehdr.e_phentsize = sizeof(Elf_Phdr); + Ehdr.e_phnum = Segments.size(); + Ehdr.e_shentsize = sizeof(Elf_Shdr); + Ehdr.e_shnum = Sections.size() + 1; + Ehdr.e_shstrndx = SectionNames->Index; } template -void BinaryObject::write(FileOutputBuffer &Out) const { - for (auto &Segment : this->Segments) { - if (Segment->Type == llvm::ELF::PT_LOAD) { - Segment->writeSegment(Out); - } - } +void Object::writeProgramHeaders(FileOutputBuffer &Out) const { + for (auto &Phdr : Segments) + Phdr->template writeHeader(Out); } -template void BinaryObject::finalize() { - for (auto &Segment : this->Segments) - Segment->finalize(); +template +void Object::writeSectionHeaders(FileOutputBuffer &Out) const { + uint8_t *Buf = Out.getBufferStart() + SHOffset; + // This reference serves to write the dummy section header at the begining + // of the file. + Elf_Shdr &Shdr = *reinterpret_cast(Buf); + Shdr.sh_name = 0; + Shdr.sh_type = SHT_NULL; + Shdr.sh_flags = 0; + Shdr.sh_addr = 0; + Shdr.sh_offset = 0; + Shdr.sh_size = 0; + Shdr.sh_link = 0; + Shdr.sh_info = 0; + Shdr.sh_addralign = 0; + Shdr.sh_entsize = 0; - // Put all segments in offset order. - auto CompareSegments = [](const SegPtr &A, const SegPtr &B) { - return A->Offset < B->Offset; - }; - std::sort(std::begin(this->Segments), std::end(this->Segments), - CompareSegments); - - uint64_t Offset = 0; - for (auto &Segment : this->Segments) { - if (Segment->Type == llvm::ELF::PT_LOAD) { - Offset = alignTo(Offset, Segment->Align); - Segment->Offset = Offset; - Offset += Segment->FileSize; - } - } - TotalSize = Offset; + for (auto &Section : Sections) + Section->template writeHeader(Out); +} + +template +void Object::writeSectionData(FileOutputBuffer &Out) const { + for (auto &Section : Sections) + Section->writeSection(Out); +} + +template void Object::write(FileOutputBuffer &Out) { + writeHeader(Out); + writeProgramHeaders(Out); + writeSectionData(Out); + writeSectionHeaders(Out); } template class Object; template class Object; template class Object; template class Object; - -template class ELFObject; -template class ELFObject; -template class ELFObject; -template class ELFObject; - -template class BinaryObject; -template class BinaryObject; -template class BinaryObject; -template class BinaryObject; diff --git a/tools/llvm-objcopy/Object.h b/tools/llvm-objcopy/Object.h index b505e60b382..d743efbde65 100644 --- a/tools/llvm-objcopy/Object.h +++ b/tools/llvm-objcopy/Object.h @@ -58,7 +58,6 @@ private: }; std::set Sections; - llvm::ArrayRef Contents; public: uint64_t Align; @@ -71,7 +70,6 @@ public: uint64_t Type; uint64_t VAddr; - Segment(llvm::ArrayRef Data) : Contents(Data) {} void finalize(); const SectionBase *firstSection() const { if (!Sections.empty()) @@ -80,7 +78,6 @@ public: } void addSection(const SectionBase *sec) { Sections.insert(sec); } template void writeHeader(llvm::FileOutputBuffer &Out) const; - void writeSegment(llvm::FileOutputBuffer &Out) const; }; class Section : public SectionBase { @@ -120,16 +117,16 @@ private: typedef typename ELFT::Ehdr Elf_Ehdr; typedef typename ELFT::Phdr Elf_Phdr; - SecPtr makeSection(const llvm::object::ELFFile &ElfFile, - const Elf_Shdr &Shdr); - void readProgramHeaders(const llvm::object::ELFFile &ElfFile); - void readSectionHeaders(const llvm::object::ELFFile &ElfFile); - -protected: StringTableSection *SectionNames; std::vector Sections; std::vector Segments; + void sortSections(); + void assignOffsets(); + SecPtr makeSection(const llvm::object::ELFFile &ElfFile, + const Elf_Shdr &Shdr); + void readProgramHeaders(const llvm::object::ELFFile &ElfFile); + void readSectionHeaders(const llvm::object::ELFFile &ElfFile); void writeHeader(llvm::FileOutputBuffer &Out) const; void writeProgramHeaders(llvm::FileOutputBuffer &Out) const; void writeSectionData(llvm::FileOutputBuffer &Out) const; @@ -145,43 +142,9 @@ public: uint32_t Flags; Object(const llvm::object::ELFObjectFile &Obj); - virtual size_t totalSize() const = 0; - virtual void finalize() = 0; - virtual void write(llvm::FileOutputBuffer &Out) const = 0; - virtual ~Object() = default; -}; - -template class ELFObject : public Object { -private: - typedef std::unique_ptr SecPtr; - typedef std::unique_ptr SegPtr; - - typedef typename ELFT::Shdr Elf_Shdr; - typedef typename ELFT::Ehdr Elf_Ehdr; - typedef typename ELFT::Phdr Elf_Phdr; - - void sortSections(); - void assignOffsets(); - -public: - ELFObject(const llvm::object::ELFObjectFile &Obj) : Object(Obj) {} - void finalize() override; - size_t totalSize() const override; - void write(llvm::FileOutputBuffer &Out) const override; + size_t totalSize() const; + void finalize(); + void write(llvm::FileOutputBuffer &Out); }; -template class BinaryObject : public Object { -private: - typedef std::unique_ptr SecPtr; - typedef std::unique_ptr SegPtr; - - uint64_t TotalSize; - -public: - BinaryObject(const llvm::object::ELFObjectFile &Obj) - : Object(Obj) {} - void finalize() override; - size_t totalSize() const override; - void write(llvm::FileOutputBuffer &Out) const override; -}; #endif diff --git a/tools/llvm-objcopy/llvm-objcopy.cpp b/tools/llvm-objcopy/llvm-objcopy.cpp index 9b233951b8d..09edc4c3327 100644 --- a/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/tools/llvm-objcopy/llvm-objcopy.cpp @@ -53,23 +53,13 @@ LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, llvm::Error E) { cl::opt InputFilename(cl::Positional, cl::desc("")); cl::opt OutputFilename(cl::Positional, cl::desc(""), cl::init("-")); -cl::opt - OutputFormat("O", cl::desc("set output format to one of the following:" - "\n\tbinary")); void CopyBinary(const ELFObjectFile &ObjFile) { std::unique_ptr Buffer; - std::unique_ptr> Obj; - if (!OutputFormat.empty() && OutputFormat != "binary") - error("invalid output format '" + OutputFormat + "'"); - - if (!OutputFormat.empty() && OutputFormat == "binary") - Obj = llvm::make_unique>(ObjFile); - else - Obj = llvm::make_unique>(ObjFile); - Obj->finalize(); + Object Obj{ObjFile}; + Obj.finalize(); ErrorOr> BufferOrErr = - FileOutputBuffer::create(OutputFilename, Obj->totalSize(), + FileOutputBuffer::create(OutputFilename, Obj.totalSize(), FileOutputBuffer::F_executable); if (BufferOrErr.getError()) error("failed to open " + OutputFilename); @@ -78,7 +68,7 @@ void CopyBinary(const ELFObjectFile &ObjFile) { std::error_code EC; if (EC) report_fatal_error(EC.message()); - Obj->write(*Buffer); + Obj.write(*Buffer); if (auto EC = Buffer->commit()) reportError(OutputFilename, EC); } -- 2.40.0