[llvm] r323480 - [llvm-objcopy] Refactor llvm-objcopy to use reader and writer objects

Shoaib Meenai via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 25 16:15:01 PST 2018


Something went very wrong with the formatting of that email, where it's basically illegible (or maybe that's just my Outlook client being silly).

In any case, I'm seeing build errors with gcc 4.8.5 with this change:

FAILED: tools/llvm-objcopy/CMakeFiles/llvm-objcopy.dir/llvm-objcopy.cpp.o
/bin/c++   -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools/llvm-objcopy -I../../../tools/llvm-objcopy -I/usr/include/libxml2 -Iinclude -I../../../include -fPIC -fvisibility-inlines-hidden -std=c++11 -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor -Wno-comment -ffunction-sections -fdata-sections -O3    -UNDEBUG  -fno-exceptions -fno-rtti -MD -MT tools/llvm-objcopy/CMakeFiles/llvm-objcopy.dir/llvm-objcopy.cpp.o -MF tools/llvm-objcopy/CMakeFiles/llvm-objcopy.dir/llvm-objcopy.cpp.o.d -o tools/llvm-objcopy/CMakeFiles/llvm-objcopy.dir/llvm-objcopy.cpp.o -c ../../../tools/llvm-objcopy/llvm-objcopy.cpp
In file included from ../../../tools/llvm-objcopy/llvm-objcopy.cpp:11:0:
../../../tools/llvm-objcopy/Object.h:533:27: error: declaration of ‘std::unique_ptr<llvm::object::Binary> llvm::ELFReader::Binary’ [-fpermissive]
   std::unique_ptr<Binary> Binary;
                           ^
In file included from ../../../include/llvm/Object/ELFObjectFile.h:24:0,
                 from ../../../tools/llvm-objcopy/Object.h:18,
                 from ../../../tools/llvm-objcopy/llvm-objcopy.cpp:11:
../../../include/llvm/Object/Binary.h:32:7: error: changes meaning of ‘Binary’ from ‘class llvm::object::Binary’ [-fpermissive]
class Binary {
       ^

From: llvm-commits <llvm-commits-bounces at lists.llvm.org> on behalf of via llvm-commits <llvm-commits at lists.llvm.org>
Reply-To: "paul.robinson at sony.com" <paul.robinson at sony.com>
Date: Thursday, January 25, 2018 at 3:54 PM
To: "jakehehrlich at google.com" <jakehehrlich at google.com>
Cc: "llvm-commits at lists.llvm.org" <llvm-commits at lists.llvm.org>
Subject: RE: [llvm] r323480 - [llvm-objcopy] Refactor llvm-objcopy to use reader and writer objects

Hi Jake, two issues with this commit, see inline.



-----Original Message-----

From: llvm-commits [mailto:llvm-commits-bounces at lists.llvm.org] On Behalf

Of Jake Ehrlich via llvm-commits

Sent: Thursday, January 25, 2018 2:46 PM

To: llvm-commits at lists.llvm.org<mailto:llvm-commits at lists.llvm.org>

Subject: [llvm] r323480 - [llvm-objcopy] Refactor llvm-objcopy to use

reader and writer objects


Author: jakehehrlich

Date: Thu Jan 25 14:46:17 2018

New Revision: 323480


URL: https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D323480-26view-3Drev&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=6hyTU63qpfKMtfyTVJdXxdDzPes25Dl60tzWRI3YCbs&e=

Log:

[llvm-objcopy] Refactor llvm-objcopy to use reader and writer objects


While writing code for input and output formats in llvm-objcopy it became

apparent that there was a code health problem. This change attempts to

solve

that problem by refactoring the code to use Reader and Writer objects that

can

read in different objects in different formats, convert them to a single

shared

internal representation, and then write them to any other representation.


New classes:

Reader: the base class used to construct instances of the internal

representation

Writer: the base class used to write out instances of the internal

representation

ELFBuilder: a helper class for ELFWriter that takes an ELFFile and

converts it

to a Object

SectionVisitor: it became necessary to remove writeSection from

SectionBase

because, under the new Reader/Writer scheme, it's possible to convert

between

ELF Types such as ELF32LE and ELF32BE. This isn't possible with

writeSection

because it (dynamically) depends on the underlying section type *and*

(statically) depends on the ELF type. Bad things would happen if the

underlying

sections for ELF32LE were used for writing to ELF64BE. To avoid this code

smell

(which would have compiled, run, and output some nonsesnse) I decoupled

writing

of sections from a class.

SectionWriter: This is just the ELFT templated implementation of

SectionVisitor. Many classes now have this class as a friend so that the

writing methods in this class can write out private data.

ELFWriter: This is the Writer that outputs to ELF

BinaryWriter: This is the Writer that outputs to Binary

ElfType: Because the ELF Type is not a part of the Object anymore we need

a way

to construct the correct default Writer based on properties of the Reader.

This

enum just keeps track of the ELF type of the input so it can be used as

the

default output type as well.


Object has correspondingly undergone some serious changes as well. It now

has

more generic methods for building and manipulating ELF binaries. This

interface

makes ELFBuilder easy enough to use and will make the BinaryReader/Builder

easy

to create as well. Most changes in this diff are cosmetic and deal with

the

fact that a method has been moved from one class to another or a change

from a

pointer to a reference. Almost no changes should result in a functional

difference (this is after all a refactor). One minor functional change was

made

and the result can be seen in remove-shstrtab-error.test. The fact that it

fails hasn't changed but the error message has changed because that

failure is

detected at a later point in the code now (because WriteSectionHeaders is

a

property of the ElfWriter *not* a property of the Object). I'd say roughly

80-90% of this code is cosmetically different, 10-19% is different but

functionally the same, and 1-5% is functionally different despite not

causing a

change in tests.


Differential Revision: https://urldefense.proofpoint.com/v2/url?u=https-3A__reviews.llvm.org_D42222&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=gZPohGddJcn5dHTT37Jc2iP4m_ObFpkT4AF1ccdkalA&e=


Added:

     llvm/trunk/test/tools/llvm-objcopy/Inputs/alloc-symtab.o

     llvm/trunk/test/tools/llvm-objcopy/binary-out-error.test

Modified:

     llvm/trunk/test/tools/llvm-objcopy/remove-shstrtab-error.test

     llvm/trunk/tools/llvm-objcopy/Object.cpp

     llvm/trunk/tools/llvm-objcopy/Object.h

     llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp

     llvm/trunk/tools/llvm-objcopy/llvm-objcopy.h


Added: llvm/trunk/test/tools/llvm-objcopy/Inputs/alloc-symtab.o

URL: https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_tools_llvm-2D&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=eZdSu5I_rE2rVzNINdjNXhOjXSgNNVAAsBH9mk3HW-Y&e=

objcopy/Inputs/alloc-symtab.o?rev=323480&view=auto

==========================================================================

====

Binary files llvm/trunk/test/tools/llvm-objcopy/Inputs/alloc-symtab.o

(added) and llvm/trunk/test/tools/llvm-objcopy/Inputs/alloc-symtab.o Thu

Jan 25 14:46:17 2018 differ


Added: llvm/trunk/test/tools/llvm-objcopy/binary-out-error.test

URL: https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_tools_llvm-2D&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=eZdSu5I_rE2rVzNINdjNXhOjXSgNNVAAsBH9mk3HW-Y&e=

objcopy/binary-out-error.test?rev=323480&view=auto

==========================================================================

====

--- llvm/trunk/test/tools/llvm-objcopy/binary-out-error.test (added)

+++ llvm/trunk/test/tools/llvm-objcopy/binary-out-error.test Thu Jan 25

14:46:17 2018

@@ -0,0 +1,2 @@

+# RUN: not llvm-objcopy -O binary %p/Inputs/alloc-symtab.o %t2 2>&1

>/dev/null | FileCheck %s --check-prefix=SYMTAB

+# SYMTAB: Cannot write symbol table '.symtab' out to binary


Modified: llvm/trunk/test/tools/llvm-objcopy/remove-shstrtab-error.test

URL: https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_tools_llvm-2D&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=eZdSu5I_rE2rVzNINdjNXhOjXSgNNVAAsBH9mk3HW-Y&e=

objcopy/remove-shstrtab-

error.test?rev=323480&r1=323479&r2=323480&view=diff

==========================================================================

====

--- llvm/trunk/test/tools/llvm-objcopy/remove-shstrtab-error.test

(original)

+++ llvm/trunk/test/tools/llvm-objcopy/remove-shstrtab-error.test Thu Jan

25 14:46:17 2018

@@ -8,4 +8,4 @@ FileHeader:

    Type:            ET_REL

    Machine:         EM_X86_64


-# CHECK: Cannot remove .shstrtab because it is the section header string

table.

+# CHECK: Cannot write section header table because section header string

table was removed.


Modified: llvm/trunk/tools/llvm-objcopy/Object.cpp

URL: https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_tools_llvm-2D&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=Jt__weu8bTTZMmQiRlU2gOsaNTUaBGk2SW-FzUGwoQw&e=

objcopy/Object.cpp?rev=323480&r1=323479&r2=323480&view=diff

==========================================================================

====

--- llvm/trunk/tools/llvm-objcopy/Object.cpp (original)

+++ llvm/trunk/tools/llvm-objcopy/Object.cpp Thu Jan 25 14:46:17 2018

@@ -30,61 +30,73 @@ using namespace llvm;

  using namespace object;

  using namespace ELF;


-template <class ELFT> void Segment::writeHeader(FileOutputBuffer &Out)

const {

+template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg)

{

    using Elf_Ehdr = typename ELFT::Ehdr;

    using Elf_Phdr = typename ELFT::Phdr;


-  uint8_t *Buf = Out.getBufferStart();

-  Buf += sizeof(Elf_Ehdr) + Index * sizeof(Elf_Phdr);

+  uint8_t *Buf = BufPtr->getBufferStart();

+  Buf += sizeof(Elf_Ehdr) + Seg.Index * sizeof(Elf_Phdr);

    Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(Buf);

-  Phdr.p_type = Type;

-  Phdr.p_flags = Flags;

-  Phdr.p_offset = Offset;

-  Phdr.p_vaddr = VAddr;

-  Phdr.p_paddr = PAddr;

-  Phdr.p_filesz = FileSize;

-  Phdr.p_memsz = MemSize;

-  Phdr.p_align = Align;

-}

-

-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);

+  Phdr.p_type = Seg.Type;

+  Phdr.p_flags = Seg.Flags;

+  Phdr.p_offset = Seg.Offset;

+  Phdr.p_vaddr = Seg.VAddr;

+  Phdr.p_paddr = Seg.PAddr;

+  Phdr.p_filesz = Seg.FileSize;

+  Phdr.p_memsz = Seg.MemSize;

+  Phdr.p_align = Seg.Align;

  }


  void SectionBase::removeSectionReferences(const SectionBase *Sec) {}

  void SectionBase::initialize(SectionTableRef SecTable) {}

  void SectionBase::finalize() {}


-template <class ELFT>

-void SectionBase::writeHeader(FileOutputBuffer &Out) const {

-  uint8_t *Buf = Out.getBufferStart();

-  Buf += HeaderOffset;

+template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase

&Sec) {

+  uint8_t *Buf = BufPtr->getBufferStart();

+  Buf += Sec.HeaderOffset;

    typename ELFT::Shdr &Shdr = *reinterpret_cast<typename ELFT::Shdr

*>(Buf);

-  Shdr.sh_name = NameIndex;

-  Shdr.sh_type = Type;

-  Shdr.sh_flags = Flags;

-  Shdr.sh_addr = Addr;

-  Shdr.sh_offset = Offset;

-  Shdr.sh_size = Size;

-  Shdr.sh_link = Link;

-  Shdr.sh_info = Info;

-  Shdr.sh_addralign = Align;

-  Shdr.sh_entsize = EntrySize;

+  Shdr.sh_name = Sec.NameIndex;

+  Shdr.sh_type = Sec.Type;

+  Shdr.sh_flags = Sec.Flags;

+  Shdr.sh_addr = Sec.Addr;

+  Shdr.sh_offset = Sec.Offset;

+  Shdr.sh_size = Sec.Size;

+  Shdr.sh_link = Sec.Link;

+  Shdr.sh_info = Sec.Info;

+  Shdr.sh_addralign = Sec.Align;

+  Shdr.sh_entsize = Sec.EntrySize;

+}

+

+SectionVisitor::~SectionVisitor() {}

+

+void BinarySectionWriter::visit(const SymbolTableSection &Sec) {

+  error("Cannot write symbol table '" + Sec.Name + "' out to binary");

+}

+

+void BinarySectionWriter::visit(const RelocationSection &Sec) {

+  error("Cannot write relocation section '" + Sec.Name + "' out to

binary");

  }


-void Section::writeSection(FileOutputBuffer &Out) const {

-  if (Type == SHT_NOBITS)

+void BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) {

+  error("Cannot write '.gnu_debuglink' out to binary");

+}

+

+void SectionWriter::visit(const Section &Sec) {

+  if (Sec.Type == SHT_NOBITS)

      return;

-  uint8_t *Buf = Out.getBufferStart() + Offset;

-  std::copy(std::begin(Contents), std::end(Contents), Buf);

+  uint8_t *Buf = Out.getBufferStart() + Sec.Offset;

+  std::copy(std::begin(Sec.Contents), std::end(Sec.Contents), Buf);

  }


-void OwnedDataSection::writeSection(FileOutputBuffer &Out) const {

-  uint8_t *Buf = Out.getBufferStart() + Offset;

-  std::copy(std::begin(Data), std::end(Data), Buf);

+void Section::accept(SectionVisitor &Visitor) const {

Visitor.visit(*this); }

+

+void SectionWriter::visit(const OwnedDataSection &Sec) {

+  uint8_t *Buf = Out.getBufferStart() + Sec.Offset;

+  std::copy(std::begin(Sec.Data), std::end(Sec.Data), Buf);

+}

+

+void OwnedDataSection::accept(SectionVisitor &Visitor) const {

+  Visitor.visit(*this);

  }


  void StringTableSection::addString(StringRef Name) {

@@ -98,8 +110,12 @@ uint32_t StringTableSection::findIndex(S


  void StringTableSection::finalize() { StrTabBuilder.finalize(); }


-void StringTableSection::writeSection(FileOutputBuffer &Out) const {

-  StrTabBuilder.write(Out.getBufferStart() + Offset);

+void SectionWriter::visit(const StringTableSection &Sec) {

+  Sec.StrTabBuilder.write(Out.getBufferStart() + Sec.Offset);

+}

+

+void StringTableSection::accept(SectionVisitor &Visitor) const {

+  Visitor.visit(*this);

  }


  static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine)

{

@@ -234,12 +250,12 @@ const Symbol *SymbolTableSection::getSym

  }


  template <class ELFT>

-void SymbolTableSectionImpl<ELFT>::writeSection(FileOutputBuffer &Out)

const {

+void ELFSectionWriter<ELFT>::visit(const SymbolTableSection &Sec) {

    uint8_t *Buf = Out.getBufferStart();

-  Buf += Offset;

+  Buf += Sec.Offset;

    typename ELFT::Sym *Sym = reinterpret_cast<typename ELFT::Sym *>(Buf);

    // Loop though symbols setting each entry of the symbol table.

-  for (auto &Symbol : Symbols) {

+  for (auto &Symbol : Sec.Symbols) {

      Sym->st_name = Symbol->NameIndex;

      Sym->st_value = Symbol->Value;

      Sym->st_size = Symbol->Size;

@@ -251,6 +267,10 @@ void SymbolTableSectionImpl<ELFT>::write

    }

  }


+void SymbolTableSection::accept(SectionVisitor &Visitor) const {

+  Visitor.visit(*this);

+}

+

  template <class SymTabType>

  void RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(

      const SectionBase *Sec) {

@@ -294,9 +314,8 @@ void setAddend(Elf_Rel_Impl<ELFT, true>

    Rela.r_addend = Addend;

  }


-template <class ELFT>

-template <class T>

-void RelocationSection<ELFT>::writeRel(T *Buf) const {

+template <class RelRange, class T>

+void writeRel(const RelRange &Relocations, T *Buf) {

    for (const auto &Reloc : Relocations) {

      Buf->r_offset = Reloc.Offset;

      setAddend(*Buf, Reloc.Addend);

@@ -306,17 +325,25 @@ void RelocationSection<ELFT>::writeRel(T

  }


  template <class ELFT>

-void RelocationSection<ELFT>::writeSection(FileOutputBuffer &Out) const {

-  uint8_t *Buf = Out.getBufferStart() + Offset;

-  if (Type == SHT_REL)

-    writeRel(reinterpret_cast<Elf_Rel *>(Buf));

+void ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {

+  uint8_t *Buf = Out.getBufferStart() + Sec.Offset;

+  if (Sec.Type == SHT_REL)

+    writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf));

    else

-    writeRel(reinterpret_cast<Elf_Rela *>(Buf));

+    writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf));

  }


-void DynamicRelocationSection::writeSection(FileOutputBuffer &Out) const

{

-  std::copy(std::begin(Contents), std::end(Contents),

-            Out.getBufferStart() + Offset);

+void RelocationSection::accept(SectionVisitor &Visitor) const {

+  Visitor.visit(*this);

+}

+

+void SectionWriter::visit(const DynamicRelocationSection &Sec) {

+  std::copy(std::begin(Sec.Contents), std::end(Sec.Contents),

+            Out.getBufferStart() + Sec.Offset);

+}

+

+void DynamicRelocationSection::accept(SectionVisitor &Visitor) const {

+  Visitor.visit(*this);

  }


  void SectionWithStrTab::removeSectionReferences(const SectionBase *Sec) {

@@ -344,8 +371,7 @@ void SectionWithStrTab::initialize(Secti


  void SectionWithStrTab::finalize() { this->Link = StrTab->Index; }


-template <class ELFT>

-void GnuDebugLinkSection<ELFT>::init(StringRef File, StringRef Data) {

+void GnuDebugLinkSection::init(StringRef File, StringRef Data) {

    FileName = sys::path::stem(File);

    // The format for the .gnu_debuglink starts with the stemmed file name

and is

    // followed by a null terminator and then the CRC32 of the file. The

CRC32

@@ -368,9 +394,7 @@ void GnuDebugLinkSection<ELFT>::init(Str

    CRC32 = ~crc.getCRC();

  }


-template <class ELFT>

-GnuDebugLinkSection<ELFT>::GnuDebugLinkSection(StringRef File)

-    : FileName(File) {

+GnuDebugLinkSection::GnuDebugLinkSection(StringRef File) : FileName(File)

{

    // Read in the file to compute the CRC of it.

    auto DebugOrErr = MemoryBuffer::getFile(File);

    if (!DebugOrErr)

@@ -380,12 +404,17 @@ GnuDebugLinkSection<ELFT>::GnuDebugLinkS

  }


  template <class ELFT>

-void GnuDebugLinkSection<ELFT>::writeSection(FileOutputBuffer &Out) const

{

-  auto Buf = Out.getBufferStart() + Offset;

+void ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {

+  auto Buf = Out.getBufferStart() + Sec.Offset;

    char *File = reinterpret_cast<char *>(Buf);

-  Elf_Word *CRC = reinterpret_cast<Elf_Word *>(Buf + Size -

sizeof(Elf_Word));

-  *CRC = CRC32;

-  std::copy(std::begin(FileName), std::end(FileName), File);

+  Elf_Word *CRC =

+      reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));

+  *CRC = Sec.CRC32;

+  std::copy(std::begin(Sec.FileName), std::end(Sec.FileName), File);

+}

+

+void GnuDebugLinkSection::accept(SectionVisitor &Visitor) const {

+  Visitor.visit(*this);

  }


  // Returns true IFF a section is wholly inside the range of a segment

@@ -427,14 +456,12 @@ static bool compareSegmentsByPAddr(const

    return A->Index < B->Index;

  }


-template <class ELFT>

-void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {

+template <class ELFT> void ELFBuilder<ELFT>::readProgramHeaders() {

    uint32_t Index = 0;

    for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {

      ArrayRef<uint8_t> Data{ElfFile.base() + Phdr.p_offset,

                             (size_t)Phdr.p_filesz};

-    Segments.emplace_back(llvm::make_unique<Segment>(Data));

-    Segment &Seg = *Segments.back();

+    Segment &Seg = Obj.addSegment(Data);

      Seg.Type = Phdr.p_type;

      Seg.Flags = Phdr.p_flags;

      Seg.OriginalOffset = Phdr.p_offset;

@@ -445,29 +472,29 @@ void Object<ELFT>::readProgramHeaders(co

      Seg.MemSize = Phdr.p_memsz;

      Seg.Align = Phdr.p_align;

      Seg.Index = Index++;

-    for (auto &Section : Sections) {

-      if (sectionWithinSegment(*Section, Seg)) {

-        Seg.addSection(&*Section);

-        if (!Section->ParentSegment ||

-            Section->ParentSegment->Offset > Seg.Offset) {

-          Section->ParentSegment = &Seg;

+    for (auto &Section : Obj.sections()) {

+      if (sectionWithinSegment(Section, Seg)) {

+        Seg.addSection(&Section);

+        if (!Section.ParentSegment ||

+            Section.ParentSegment->Offset > Seg.Offset) {

+          Section.ParentSegment = &Seg;

          }

        }

      }

    }

    // Now we do an O(n^2) loop through the segments in order to match up

    // segments.

-  for (auto &Child : Segments) {

-    for (auto &Parent : Segments) {

+  for (auto &Child : Obj.segments()) {

+    for (auto &Parent : Obj.segments()) {

        // Every segment will overlap with itself but we don't want a

segment to

        // be it's own parent so we avoid that situation.

-      if (&Child != &Parent && segmentOverlapsSegment(*Child, *Parent)) {

+      if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) {

          // We want a canonical "most parental" segment but this requires

          // inspecting the ParentSegment.

-        if (compareSegmentsByOffset(Parent.get(), Child.get()))

-          if (Child->ParentSegment == nullptr ||

-              compareSegmentsByOffset(Parent.get(), Child-

>ParentSegment)) {

-            Child->ParentSegment = Parent.get();

+        if (compareSegmentsByOffset(&Parent, &Child))

+          if (Child.ParentSegment == nullptr ||

+              compareSegmentsByOffset(&Parent, Child.ParentSegment)) {

+            Child.ParentSegment = &Parent;

            }

        }

      }

@@ -475,9 +502,7 @@ void Object<ELFT>::readProgramHeaders(co

  }


  template <class ELFT>

-void Object<ELFT>::initSymbolTable(const object::ELFFile<ELFT> &ElfFile,

-                                   SymbolTableSection *SymTab,

-                                   SectionTableRef SecTable) {

+void ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {

    const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab-

>Index));

    StringRef StrTabData =

unwrapOrError(ElfFile.getStringTableForSymtab(Shdr));


@@ -486,14 +511,14 @@ void Object<ELFT>::initSymbolTable(const

      StringRef Name = unwrapOrError(Sym.getName(StrTabData));


      if (Sym.st_shndx >= SHN_LORESERVE) {

-      if (!isValidReservedSectionIndex(Sym.st_shndx, Machine)) {

+      if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {

          error(

              "Symbol '" + Name +

              "' has unsupported value greater than or equal to

SHN_LORESERVE: " +

              Twine(Sym.st_shndx));

        }

      } else if (Sym.st_shndx != SHN_UNDEF) {

-      DefSection = SecTable.getSection(

+      DefSection = Obj.sections().getSection(

            Sym.st_shndx,

            "Symbol '" + Name + "' is defined in invalid section with index

" +

                Twine(Sym.st_shndx));

@@ -512,9 +537,9 @@ static void getAddend(uint64_t &ToSet, c

    ToSet = Rela.r_addend;

  }


-template <class ELFT, class T>

-void initRelocations(RelocationSection<ELFT> *Relocs,

-                     SymbolTableSection *SymbolTable, T RelRange) {

+template <class T>

+void initRelocations(RelocationSection *Relocs, SymbolTableSection

*SymbolTable,

+                     T RelRange) {

    for (const auto &Rel : RelRange) {

      Relocation ToAdd;

      ToAdd.Offset = Rel.r_offset;

@@ -540,147 +565,190 @@ T *SectionTableRef::getSectionOfType(uin

  }


  template <class ELFT>

-std::unique_ptr<SectionBase>

-Object<ELFT>::makeSection(const object::ELFFile<ELFT> &ElfFile,

-                          const Elf_Shdr &Shdr) {

+SectionBase &ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {

    ArrayRef<uint8_t> Data;

    switch (Shdr.sh_type) {

    case SHT_REL:

    case SHT_RELA:

      if (Shdr.sh_flags & SHF_ALLOC) {

        Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));

-      return llvm::make_unique<DynamicRelocationSection>(Data);

+      return Obj.addSection<DynamicRelocationSection>(Data);

      }

-    return llvm::make_unique<RelocationSection<ELFT>>();

+    return Obj.addSection<RelocationSection>();

    case SHT_STRTAB:

      // If a string table is allocated we don't want to mess with it. That

would

      // mean altering the memory image. There are no special link types or

      // anything so we can just use a Section.

      if (Shdr.sh_flags & SHF_ALLOC) {

        Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));

-      return llvm::make_unique<Section>(Data);

+      return Obj.addSection<Section>(Data);

      }

-    return llvm::make_unique<StringTableSection>();

+    return Obj.addSection<StringTableSection>();

    case SHT_HASH:

    case SHT_GNU_HASH:

      // Hash tables should refer to SHT_DYNSYM which we're not going to

change.

      // Because of this we don't need to mess with the hash tables either.

      Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));

-    return llvm::make_unique<Section>(Data);

+    return Obj.addSection<Section>(Data);

    case SHT_DYNSYM:

      Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));

-    return llvm::make_unique<DynamicSymbolTableSection>(Data);

+    return Obj.addSection<DynamicSymbolTableSection>(Data);

    case SHT_DYNAMIC:

      Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));

-    return llvm::make_unique<DynamicSection>(Data);

+    return Obj.addSection<DynamicSection>(Data);

    case SHT_SYMTAB: {

-    auto SymTab = llvm::make_unique<SymbolTableSectionImpl<ELFT>>();

-    SymbolTable = SymTab.get();

-    return std::move(SymTab);

+    auto &SymTab = Obj.addSection<SymbolTableSection>();

+    Obj.SymbolTable = &SymTab;

+    return SymTab;

    }

    case SHT_NOBITS:

-    return llvm::make_unique<Section>(Data);

+    return Obj.addSection<Section>(Data);

    default:

      Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));

-    return llvm::make_unique<Section>(Data);

+    return Obj.addSection<Section>(Data);

    }

  }


-template <class ELFT>

-SectionTableRef Object<ELFT>::readSectionHeaders(const ELFFile<ELFT>

&ElfFile) {

+template <class ELFT> void ELFBuilder<ELFT>::readSectionHeaders() {

    uint32_t Index = 0;

    for (const auto &Shdr : unwrapOrError(ElfFile.sections())) {

      if (Index == 0) {

        ++Index;

        continue;

      }

-    SecPtr Sec = makeSection(ElfFile, Shdr);

-    Sec->Name = unwrapOrError(ElfFile.getSectionName(&Shdr));

-    Sec->Type = Shdr.sh_type;

-    Sec->Flags = Shdr.sh_flags;

-    Sec->Addr = Shdr.sh_addr;

-    Sec->Offset = Shdr.sh_offset;

-    Sec->OriginalOffset = Shdr.sh_offset;

-    Sec->Size = Shdr.sh_size;

-    Sec->Link = Shdr.sh_link;

-    Sec->Info = Shdr.sh_info;

-    Sec->Align = Shdr.sh_addralign;

-    Sec->EntrySize = Shdr.sh_entsize;

-    Sec->Index = Index++;

-    Sections.push_back(std::move(Sec));

+    auto &Sec = makeSection(Shdr);

+    Sec.Name = unwrapOrError(ElfFile.getSectionName(&Shdr));

+    Sec.Type = Shdr.sh_type;

+    Sec.Flags = Shdr.sh_flags;

+    Sec.Addr = Shdr.sh_addr;

+    Sec.Offset = Shdr.sh_offset;

+    Sec.OriginalOffset = Shdr.sh_offset;

+    Sec.Size = Shdr.sh_size;

+    Sec.Link = Shdr.sh_link;

+    Sec.Info = Shdr.sh_info;

+    Sec.Align = Shdr.sh_addralign;

+    Sec.EntrySize = Shdr.sh_entsize;

+    Sec.Index = Index++;

    }


-  SectionTableRef SecTable(Sections);

-

    // Now that all of the sections have been added we can fill out some

extra

    // details about symbol tables. We need the symbol table filled out

before

    // any relocations.

-  if (SymbolTable) {

-    SymbolTable->initialize(SecTable);

-    initSymbolTable(ElfFile, SymbolTable, SecTable);

+  if (Obj.SymbolTable) {

+    Obj.SymbolTable->initialize(Obj.sections());

+    initSymbolTable(Obj.SymbolTable);

    }


    // Now that all sections and symbols have been added we can add

    // relocations that reference symbols and set the link and info fields

for

    // relocation sections.

-  for (auto &Section : Sections) {

-    if (Section.get() == SymbolTable)

+  for (auto &Section : Obj.sections()) {

+    if (&Section == Obj.SymbolTable)

        continue;

-    Section->initialize(SecTable);

-    if (auto RelSec = dyn_cast<RelocationSection<ELFT>>(Section.get())) {

+    Section.initialize(Obj.sections());

+    if (auto RelSec = dyn_cast<RelocationSection>(&Section)) {

        auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec-

>Index;

        if (RelSec->Type == SHT_REL)

-        initRelocations(RelSec, SymbolTable,

unwrapOrError(ElfFile.rels(Shdr)));

+        initRelocations(RelSec, Obj.SymbolTable,

+                        unwrapOrError(ElfFile.rels(Shdr)));

        else

-        initRelocations(RelSec, SymbolTable,

+        initRelocations(RelSec, Obj.SymbolTable,

                          unwrapOrError(ElfFile.relas(Shdr)));

      }

    }

-

-  return SecTable;

  }


-template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT>

&Obj) {

-  const auto &ElfFile = *Obj.getELFFile();

+template <class ELFT> void ELFBuilder<ELFT>::build() {

    const auto &Ehdr = *ElfFile.getHeader();


-  std::copy(Ehdr.e_ident, Ehdr.e_ident + 16, Ident);

-  Type = Ehdr.e_type;

-  Machine = Ehdr.e_machine;

-  Version = Ehdr.e_version;

-  Entry = Ehdr.e_entry;

-  Flags = Ehdr.e_flags;

-

-  SectionTableRef SecTable = readSectionHeaders(ElfFile);

-  readProgramHeaders(ElfFile);

-

-  SectionNames = SecTable.getSectionOfType<StringTableSection>(

-      Ehdr.e_shstrndx,

-      "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf

header " +

-          " is invalid",

-      "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) + " in elf

header " +

-          " is not a string table");

+  std::copy(Ehdr.e_ident, Ehdr.e_ident + 16, Obj.Ident);

+  Obj.Type = Ehdr.e_type;

+  Obj.Machine = Ehdr.e_machine;

+  Obj.Version = Ehdr.e_version;

+  Obj.Entry = Ehdr.e_entry;

+  Obj.Flags = Ehdr.e_flags;

+

+  readSectionHeaders();

+  readProgramHeaders();

+

+  Obj.SectionNames =

+      Obj.sections().template getSectionOfType<StringTableSection>(

+          Ehdr.e_shstrndx,

+          "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +

+              " in elf header " + " is invalid",

+          "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +

+              " in elf header " + " is not a string table");

+}

+

+// A generic size function which computes sizes of any random access

range.

+template <class R> size_t size(R &&Range) {

+  return static_cast<size_t>(std::end(Range) - std::begin(Range));

+}

+

+Writer::~Writer() {}

+

+Reader::~Reader() {}

+

+ELFReader::ELFReader(StringRef File) {

+  auto BinaryOrErr = createBinary(File);

+  if (!BinaryOrErr)

+    reportError(File, BinaryOrErr.takeError());

+  auto Bin = std::move(BinaryOrErr.get());

+  std::tie(Binary, Data) = Bin.takeBinary();

+}

+

+ElfType ELFReader::getElfType() const {

+  if (auto *o = dyn_cast<ELFObjectFile<ELF32LE>>(Binary.get()))

+    return ELFT_ELF32LE;

+  if (auto *o = dyn_cast<ELFObjectFile<ELF64LE>>(Binary.get()))

+    return ELFT_ELF64LE;

+  if (auto *o = dyn_cast<ELFObjectFile<ELF32BE>>(Binary.get()))

+    return ELFT_ELF32BE;

+  if (auto *o = dyn_cast<ELFObjectFile<ELF64BE>>(Binary.get()))

+    return ELFT_ELF64BE;



I'm getting "unused variable" warnings on the above.  Probably you

should be using isa<> rather than dyn_cast to a throwaway variable.



+  llvm_unreachable("Invalid ELFType");

+}

+

+std::unique_ptr<Object> ELFReader::create() const {

+  auto Obj = llvm::make_unique<Object>(Data);

+  if (auto *o = dyn_cast<ELFObjectFile<ELF32LE>>(Binary.get())) {

+    ELFBuilder<ELF32LE> Builder(*o, *Obj);

+    Builder.build();

+    return Obj;

+  } else if (auto *o = dyn_cast<ELFObjectFile<ELF64LE>>(Binary.get())) {

+    ELFBuilder<ELF64LE> Builder(*o, *Obj);

+    Builder.build();

+    return Obj;

+  } else if (auto *o = dyn_cast<ELFObjectFile<ELF32BE>>(Binary.get())) {

+    ELFBuilder<ELF32BE> Builder(*o, *Obj);

+    Builder.build();

+    return Obj;

+  } else if (auto *o = dyn_cast<ELFObjectFile<ELF64BE>>(Binary.get())) {

+    ELFBuilder<ELF64BE> Builder(*o, *Obj);

+    Builder.build();

+    return Obj;

+  }

+  error("Invalid file type");

  }


-template <class ELFT>

-void Object<ELFT>::writeHeader(FileOutputBuffer &Out) const {

-  uint8_t *Buf = Out.getBufferStart();

+template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {

+  uint8_t *Buf = BufPtr->getBufferStart();

    Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(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;

+  std::copy(Obj.Ident, Obj.Ident + 16, Ehdr.e_ident);

+  Ehdr.e_type = Obj.Type;

+  Ehdr.e_machine = Obj.Machine;

+  Ehdr.e_version = Obj.Version;

+  Ehdr.e_entry = Obj.Entry;

    Ehdr.e_phoff = sizeof(Elf_Ehdr);

-  Ehdr.e_flags = Flags;

+  Ehdr.e_flags = Obj.Flags;

    Ehdr.e_ehsize = sizeof(Elf_Ehdr);

    Ehdr.e_phentsize = sizeof(Elf_Phdr);

-  Ehdr.e_phnum = Segments.size();

+  Ehdr.e_phnum = size(Obj.segments());

    Ehdr.e_shentsize = sizeof(Elf_Shdr);

    if (WriteSectionHeaders) {

-    Ehdr.e_shoff = SHOffset;

-    Ehdr.e_shnum = Sections.size() + 1;

-    Ehdr.e_shstrndx = SectionNames->Index;

+    Ehdr.e_shoff = Obj.SHOffset;

+    Ehdr.e_shnum = size(Obj.sections()) + 1;

+    Ehdr.e_shstrndx = Obj.SectionNames->Index;

    } else {

      Ehdr.e_shoff = 0;

      Ehdr.e_shnum = 0;

@@ -688,15 +756,13 @@ void Object<ELFT>::writeHeader(FileOutpu

    }

  }


-template <class ELFT>

-void Object<ELFT>::writeProgramHeaders(FileOutputBuffer &Out) const {

-  for (auto &Phdr : Segments)

-    Phdr->template writeHeader<ELFT>(Out);

+template <class ELFT> void ELFWriter<ELFT>::writePhdrs() {

+  for (auto &Seg : Obj.segments())

+    writePhdr(Seg);

  }


-template <class ELFT>

-void Object<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {

-  uint8_t *Buf = Out.getBufferStart() + SHOffset;

+template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {

+  uint8_t *Buf = BufPtr->getBufferStart() + Obj.SHOffset;

    // This reference serves to write the dummy section header at the

begining

    // of the file. It is not used for anything else

    Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(Buf);

@@ -711,19 +777,16 @@ void Object<ELFT>::writeSectionHeaders(F

    Shdr.sh_addralign = 0;

    Shdr.sh_entsize = 0;


-  for (auto &Section : Sections)

-    Section->template writeHeader<ELFT>(Out);

+  for (auto &Sec : Obj.sections())

+    writeShdr(Sec);

  }


-template <class ELFT>

-void Object<ELFT>::writeSectionData(FileOutputBuffer &Out) const {

-  for (auto &Section : Sections)

-    Section->writeSection(Out);

+template <class ELFT> void ELFWriter<ELFT>::writeSectionData() {

+  for (auto &Sec : Obj.sections())

+    Sec.accept(*SecWriter);

  }


-template <class ELFT>

-void Object<ELFT>::removeSections(

-    std::function<bool(const SectionBase &)> ToRemove) {

+void Object::removeSections(std::function<bool(const SectionBase &)>

ToRemove) {


    auto Iter = std::stable_partition(

        std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {

@@ -737,10 +800,7 @@ void Object<ELFT>::removeSections(

        });

    if (SymbolTable != nullptr && ToRemove(*SymbolTable))

      SymbolTable = nullptr;

-  if (ToRemove(*SectionNames)) {

-    if (WriteSectionHeaders)

-      error("Cannot remove " + SectionNames->Name +

-            " because it is the section header string table.");

+  if (SectionNames != nullptr && ToRemove(*SectionNames)) {

      SectionNames = nullptr;

    }

    // Now make sure there are no remaining references to the sections that

will

@@ -756,18 +816,7 @@ void Object<ELFT>::removeSections(

    Sections.erase(Iter, std::end(Sections));

  }


-template <class ELFT>

-void Object<ELFT>::addSection(StringRef SecName, ArrayRef<uint8_t> Data)

{

-  auto Sec = llvm::make_unique<OwnedDataSection>(SecName, Data);

-  Sec->OriginalOffset = ~0ULL;

-  Sections.push_back(std::move(Sec));

-}

-

-template <class ELFT> void Object<ELFT>::addGnuDebugLink(StringRef File)

{

-

Sections.emplace_back(llvm::make_unique<GnuDebugLinkSection<ELFT>>(File));

-}

-

-template <class ELFT> void ELFObject<ELFT>::sortSections() {

+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) {

@@ -832,8 +881,8 @@ static uint64_t LayoutSegments(std::vect

  // does not have a ParentSegment. It returns either the offset given if

all

  // sections had a ParentSegment or an offset one past the last section if

there

  // was a section that didn't have a ParentSegment.

-template <class SecPtr>

-static uint64_t LayoutSections(std::vector<SecPtr> &Sections, uint64_t

Offset) {

+template <class Range>

+static uint64_t LayoutSections(Range Sections, uint64_t Offset) {

    // Now the offset of every segment has been set we can assign the

offsets

    // of each section. For sections that are covered by a segment we

should use

    // the segment's original offset and the section's original offset to

compute

@@ -842,28 +891,28 @@ static uint64_t LayoutSections(std::vect

    // covered by segments we can just bump Offset to the next valid

location.

    uint32_t Index = 1;

    for (auto &Section : Sections) {

-    Section->Index = Index++;

-    if (Section->ParentSegment != nullptr) {

-      auto Segment = Section->ParentSegment;

-      Section->Offset =

-          Segment->Offset + (Section->OriginalOffset - Segment-

>OriginalOffset);

+    Section.Index = Index++;

+    if (Section.ParentSegment != nullptr) {

+      auto Segment = *Section.ParentSegment;

+      Section.Offset =

+          Segment.Offset + (Section.OriginalOffset -

Segment.OriginalOffset);

      } else {

-      Offset = alignTo(Offset, Section->Align == 0 ? 1 : Section->Align);

-      Section->Offset = Offset;

-      if (Section->Type != SHT_NOBITS)

-        Offset += Section->Size;

+      Offset = alignTo(Offset, Section.Align == 0 ? 1 : Section.Align);

+      Section.Offset = Offset;

+      if (Section.Type != SHT_NOBITS)

+        Offset += Section.Size;

      }

    }

    return Offset;

  }


-template <class ELFT> void ELFObject<ELFT>::assignOffsets() {

+template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {

    // We need a temporary list of segments that has a special order to it

    // so that we know that anytime ->ParentSegment is set that segment has

    // already had its offset properly set.

    std::vector<Segment *> OrderedSegments;

-  for (auto &Segment : this->Segments)

-    OrderedSegments.push_back(Segment.get());

+  for (auto &Segment : Obj.segments())

+    OrderedSegments.push_back(&Segment);

    OrderSegments(OrderedSegments);

    // The size of ELF + program headers will not change so it is ok to

assume

    // that the first offset of the first segment is a good place to start

@@ -876,72 +925,88 @@ template <class ELFT> void ELFObject<ELF

      Offset = sizeof(Elf_Ehdr);

    }

    Offset = LayoutSegments(OrderedSegments, Offset);

-  Offset = LayoutSections(this->Sections, Offset);

+  Offset = LayoutSections(Obj.sections(), Offset);

    // If we need to write the section header table out then we need to

align the

    // Offset so that SHOffset is valid.

-  if (this->WriteSectionHeaders)

+  if (WriteSectionHeaders)

      Offset = alignTo(Offset, sizeof(typename ELFT::Addr));

-  this->SHOffset = Offset;

+  Obj.SHOffset = Offset;

  }


-template <class ELFT> size_t ELFObject<ELFT>::totalSize() const {

+template <class ELFT> size_t ELFWriter<ELFT>::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.

-  auto NullSectionSize = this->WriteSectionHeaders ? sizeof(Elf_Shdr) :

0;

-  return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr) +

+  auto NullSectionSize = WriteSectionHeaders ? sizeof(Elf_Shdr) : 0;

+  return Obj.SHOffset + size(Obj.sections()) * sizeof(Elf_Shdr) +

           NullSectionSize;

  }


-template <class ELFT> void ELFObject<ELFT>::write(FileOutputBuffer &Out)

const {

-  this->writeHeader(Out);

-  this->writeProgramHeaders(Out);

-  this->writeSectionData(Out);

-  if (this->WriteSectionHeaders)

-    this->writeSectionHeaders(Out);

-}

+template <class ELFT> void ELFWriter<ELFT>::write() {

+  writeEhdr();

+  writePhdrs();

+  writeSectionData();

+  if (WriteSectionHeaders)

+    writeShdrs();

+  if (auto E = BufPtr->commit())

+    reportError(File, errorToErrorCode(std::move(E)));

+}

+

+void Writer::createBuffer(uint64_t Size) {

+  auto BufferOrErr =

+      FileOutputBuffer::create(File, Size,

FileOutputBuffer::F_executable);

+  handleAllErrors(BufferOrErr.takeError(), [this](const ErrorInfoBase &)

{

+    error("failed to open " + File);

+  });

+  BufPtr = std::move(*BufferOrErr);

+}

+

+template <class ELFT> void ELFWriter<ELFT>::finalize() {

+  // It could happen that SectionNames has been removed and yet the user

wants

+  // a section header table output. We need to throw an error if a user

tries

+  // to do that.

+  if (Obj.SectionNames == nullptr && WriteSectionHeaders)

+    error("Cannot write section header table because section header

string "

+          "table was removed.");


-template <class ELFT> void ELFObject<ELFT>::finalize() {

    // Make sure we add the names of all the sections.

-  if (this->SectionNames != nullptr)

-    for (const auto &Section : this->Sections) {

-      this->SectionNames->addString(Section->Name);

+  if (Obj.SectionNames != nullptr)

+    for (const auto &Section : Obj.sections()) {

+      Obj.SectionNames->addString(Section.Name);

      }

    // Make sure we add the names of all the symbols.

-  if (this->SymbolTable != nullptr)

-    this->SymbolTable->addSymbolNames();

+  if (Obj.SymbolTable != nullptr)

+    Obj.SymbolTable->addSymbolNames();


-  sortSections();

+  Obj.sortSections();

    assignOffsets();


    // Finalize SectionNames first so that we can assign name indexes.

-  if (this->SectionNames != nullptr)

-    this->SectionNames->finalize();

+  if (Obj.SectionNames != nullptr)

+    Obj.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) {

-    Section->HeaderOffset = Offset;

+  uint64_t Offset = Obj.SHOffset + sizeof(Elf_Shdr);

+  for (auto &Section : Obj.sections()) {

+    Section.HeaderOffset = Offset;

      Offset += sizeof(Elf_Shdr);

-    if (this->WriteSectionHeaders)

-      Section->NameIndex = this->SectionNames->findIndex(Section->Name);

-    Section->finalize();

+    if (WriteSectionHeaders)

+      Section.NameIndex = Obj.SectionNames->findIndex(Section.Name);

+    Section.finalize();

    }

-}


-template <class ELFT> size_t BinaryObject<ELFT>::totalSize() const {

-  return TotalSize;

+  createBuffer(totalSize());

+  SecWriter = llvm::make_unique<ELFSectionWriter<ELFT>>(*BufPtr);

  }


-template <class ELFT>

-void BinaryObject<ELFT>::write(FileOutputBuffer &Out) const {

-  for (auto &Section : this->Sections) {

-    if ((Section->Flags & SHF_ALLOC) == 0)

+void BinaryWriter::write() {

+  for (auto &Section : Obj.sections()) {

+    if ((Section.Flags & SHF_ALLOC) == 0)

        continue;

-    Section->writeSection(Out);

+    Section.accept(*SecWriter);

    }

  }


-template <class ELFT> void BinaryObject<ELFT>::finalize() {

+void BinaryWriter::finalize() {

    // TODO: Create a filter range to construct OrderedSegments from so

that this

    // code can be deduped with assignOffsets above. This should also solve

the

    // todo below for LayoutSections.

@@ -950,10 +1015,9 @@ template <class ELFT> void BinaryObject<

    // already had it's offset properly set. We only want to consider the

segments

    // that will affect layout of allocated sections so we only add those.

    std::vector<Segment *> OrderedSegments;

-  for (auto &Section : this->Sections) {

-    if ((Section->Flags & SHF_ALLOC) != 0 &&

-        Section->ParentSegment != nullptr) {

-      OrderedSegments.push_back(Section->ParentSegment);

+  for (auto &Section : Obj.sections()) {

+    if ((Section.Flags & SHF_ALLOC) != 0 && Section.ParentSegment !=

nullptr) {

+      OrderedSegments.push_back(Section.ParentSegment);

      }

    }


@@ -1004,12 +1068,12 @@ template <class ELFT> void BinaryObject<

    // not hold. Then pass such a range to LayoutSections instead of

constructing

    // AllocatedSections here.

    std::vector<SectionBase *> AllocatedSections;

-  for (auto &Section : this->Sections) {

-    if ((Section->Flags & SHF_ALLOC) == 0)

+  for (auto &Section : Obj.sections()) {

+    if ((Section.Flags & SHF_ALLOC) == 0)

        continue;

-    AllocatedSections.push_back(Section.get());

+    AllocatedSections.push_back(&Section);

    }

-  LayoutSections(AllocatedSections, Offset);

+  LayoutSections(make_pointee_range(AllocatedSections), Offset);


    // Now that every section has been laid out we just need to compute the

total

    // file size. This might not be the same as the offset returned by

@@ -1020,23 +1084,21 @@ template <class ELFT> void BinaryObject<

      if (Section->Type != SHT_NOBITS)

        TotalSize = std::max(TotalSize, Section->Offset + Section->Size);

    }

+

+  createBuffer(TotalSize);

+  SecWriter = llvm::make_unique<BinarySectionWriter>(*BufPtr);

  }


  namespace llvm {


-template class Object<ELF64LE>;

-template class Object<ELF64BE>;

-template class Object<ELF32LE>;

-template class Object<ELF32BE>;

-

-template class ELFObject<ELF64LE>;

-template class ELFObject<ELF64BE>;

-template class ELFObject<ELF32LE>;

-template class ELFObject<ELF32BE>;

-

-template class BinaryObject<ELF64LE>;

-template class BinaryObject<ELF64BE>;

-template class BinaryObject<ELF32LE>;

-template class BinaryObject<ELF32BE>;

+template class ELFBuilder<ELF64LE>;

+template class ELFBuilder<ELF64BE>;

+template class ELFBuilder<ELF32LE>;

+template class ELFBuilder<ELF32BE>;

+

+template class ELFWriter<ELF64LE>;

+template class ELFWriter<ELF64BE>;

+template class ELFWriter<ELF32LE>;

+template class ELFWriter<ELF32BE>;


  } // end namespace llvm


Modified: llvm/trunk/tools/llvm-objcopy/Object.h

URL: https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_tools_llvm-2D&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=Jt__weu8bTTZMmQiRlU2gOsaNTUaBGk2SW-FzUGwoQw&e=

objcopy/Object.h?rev=323480&r1=323479&r2=323480&view=diff

==========================================================================

====

--- llvm/trunk/tools/llvm-objcopy/Object.h (original)

+++ llvm/trunk/tools/llvm-objcopy/Object.h Thu Jan 25 14:46:17 2018

@@ -16,6 +16,7 @@

  #include "llvm/BinaryFormat/ELF.h"

  #include "llvm/MC/StringTableBuilder.h"

  #include "llvm/Object/ELFObjectFile.h"

+#include "llvm/Support/FileOutputBuffer.h"

  #include "llvm/Support/JamCRC.h"

  #include <cstddef>

  #include <cstdint>

@@ -26,25 +27,159 @@


  namespace llvm {


-class FileOutputBuffer;

  class SectionBase;

+class Section;

+class OwnedDataSection;

+class StringTableSection;

+class SymbolTableSection;

+class RelocationSection;

+class DynamicRelocationSection;

+class GnuDebugLinkSection;

  class Segment;

+class Object;


  class SectionTableRef {

  private:

-  ArrayRef<std::unique_ptr<SectionBase>> Sections;

+  MutableArrayRef<std::unique_ptr<SectionBase>> Sections;


  public:

-  SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs)

+  using iterator = pointee_iterator<std::unique_ptr<SectionBase> *>;

+

+  SectionTableRef(MutableArrayRef<std::unique_ptr<SectionBase>> Secs)

        : Sections(Secs) {}

    SectionTableRef(const SectionTableRef &) = default;


+  iterator begin() { return iterator(Sections.data()); }

+  iterator end() { return iterator(Sections.data() + Sections.size()); }

+

    SectionBase *getSection(uint16_t Index, Twine ErrMsg);


    template <class T>

    T *getSectionOfType(uint16_t Index, Twine IndexErrMsg, Twine

TypeErrMsg);

  };


+enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };

+

+class SectionVisitor {

+public:

+  virtual ~SectionVisitor();

+

+  virtual void visit(const Section &Sec) = 0;

+  virtual void visit(const OwnedDataSection &Sec) = 0;

+  virtual void visit(const StringTableSection &Sec) = 0;

+  virtual void visit(const SymbolTableSection &Sec) = 0;

+  virtual void visit(const RelocationSection &Sec) = 0;

+  virtual void visit(const DynamicRelocationSection &Sec) = 0;

+  virtual void visit(const GnuDebugLinkSection &Sec) = 0;

+};

+

+class SectionWriter : public SectionVisitor {

+protected:

+  FileOutputBuffer &Out;

+

+public:

+  virtual ~SectionWriter(){};

+

+  void visit(const Section &Sec) override;

+  void visit(const OwnedDataSection &Sec) override;

+  void visit(const StringTableSection &Sec) override;

+  void visit(const DynamicRelocationSection &Sec) override;

+  virtual void visit(const SymbolTableSection &Sec) override = 0;

+  virtual void visit(const RelocationSection &Sec) override = 0;

+  virtual void visit(const GnuDebugLinkSection &Sec) override = 0;

+

+  SectionWriter(FileOutputBuffer &Buf) : Out(Buf) {}

+};

+

+template <class ELFT> class ELFSectionWriter : public SectionWriter {

+private:

+  using Elf_Word = typename ELFT::Word;

+  using Elf_Rel = typename ELFT::Rel;

+  using Elf_Rela = typename ELFT::Rela;

+

+public:

+  virtual ~ELFSectionWriter() {}

+  void visit(const SymbolTableSection &Sec) override;

+  void visit(const RelocationSection &Sec) override;

+  void visit(const GnuDebugLinkSection &Sec) override;

+

+  ELFSectionWriter(FileOutputBuffer &Buf) : SectionWriter(Buf) {}

+};

+

+#define MAKE_SEC_WRITER_FRIEND

\

+  friend class SectionWriter;

\

+  template <class ELFT> friend class ELFSectionWriter;

+

+class BinarySectionWriter : public SectionWriter {

+public:

+  virtual ~BinarySectionWriter() {}

+

+  void visit(const SymbolTableSection &Sec) override;

+  void visit(const RelocationSection &Sec) override;

+  void visit(const GnuDebugLinkSection &Sec) override;

+  BinarySectionWriter(FileOutputBuffer &Buf) : SectionWriter(Buf) {}

+};

+

+class Writer {

+protected:

+  StringRef File;

+  Object &Obj;

+  std::unique_ptr<FileOutputBuffer> BufPtr;

+

+  void createBuffer(uint64_t Size);

+

+public:

+  virtual ~Writer();

+

+  virtual void finalize() = 0;

+  virtual void write() = 0;

+

+  Writer(StringRef File, Object &Obj) : File(File), Obj(Obj) {}

+};

+

+template <class ELFT> class ELFWriter : public Writer {

+private:

+  using Elf_Shdr = typename ELFT::Shdr;

+  using Elf_Phdr = typename ELFT::Phdr;

+  using Elf_Ehdr = typename ELFT::Ehdr;

+

+  void writeEhdr();

+  void writePhdr(const Segment &Seg);

+  void writeShdr(const SectionBase &Sec);

+

+  void writePhdrs();

+  void writeShdrs();

+  void writeSectionData();

+

+  void assignOffsets();

+

+  std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;

+

+  size_t totalSize() const;

+

+public:

+  virtual ~ELFWriter() {}

+  bool WriteSectionHeaders = true;

+

+  void finalize() override;

+  void write() override;

+  ELFWriter(StringRef File, Object &Obj, bool WSH)

+      : Writer(File, Obj), WriteSectionHeaders(WSH) {}

+};

+

+class BinaryWriter : public Writer {

+private:

+  std::unique_ptr<BinarySectionWriter> SecWriter;

+

+  uint64_t TotalSize;

+

+public:

+  ~BinaryWriter() {}

+  void finalize() override;

+  void write() override;

+  BinaryWriter(StringRef File, Object &Obj) : Writer(File, Obj) {}

+};

+

  class SectionBase {

  public:

    StringRef Name;

@@ -69,8 +204,7 @@ public:

    virtual void initialize(SectionTableRef SecTable);

    virtual void finalize();

    virtual void removeSectionReferences(const SectionBase *Sec);

-  template <class ELFT> void writeHeader(FileOutputBuffer &Out) const;

-  virtual void writeSection(FileOutputBuffer &Out) const = 0;

+  virtual void accept(SectionVisitor &Visitor) const = 0;

  };


  class Segment {

@@ -113,21 +247,23 @@ public:


    void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }

    void addSection(const SectionBase *Sec) { Sections.insert(Sec); }

-  template <class ELFT> void writeHeader(FileOutputBuffer &Out) const;

-  void writeSegment(FileOutputBuffer &Out) const;

  };


  class Section : public SectionBase {

+  MAKE_SEC_WRITER_FRIEND

+

  private:

    ArrayRef<uint8_t> Contents;


  public:

    Section(ArrayRef<uint8_t> Data) : Contents(Data) {}


-  void writeSection(FileOutputBuffer &Out) const override;

+  void accept(SectionVisitor &Visitor) const override;

  };


  class OwnedDataSection : public SectionBase {

+  MAKE_SEC_WRITER_FRIEND

+

  private:

    std::vector<uint8_t> Data;


@@ -137,8 +273,10 @@ public:

      Name = SecName;

      Type = ELF::SHT_PROGBITS;

      Size = Data.size();

+    OriginalOffset = std::numeric_limits<uint64_t>::max();

    }

-  void writeSection(FileOutputBuffer &Out) const override;

+

+  void accept(SectionVisitor &Sec) const override;

  };


  // There are two types of string tables that can exist, dynamic and not

dynamic.

@@ -150,6 +288,8 @@ public:

  // classof method checks that the particular instance is not allocated.

This

  // then agrees with the makeSection method used to construct most

sections.

  class StringTableSection : public SectionBase {

+  MAKE_SEC_WRITER_FRIEND

+

  private:

    StringTableBuilder StrTabBuilder;


@@ -161,7 +301,7 @@ public:

    void addString(StringRef Name);

    uint32_t findIndex(StringRef Name) const;

    void finalize() override;

-  void writeSection(FileOutputBuffer &Out) const override;

+  void accept(SectionVisitor &Visitor) const override;


    static bool classof(const SectionBase *S) {

      if (S->Flags & ELF::SHF_ALLOC)

@@ -200,6 +340,8 @@ struct Symbol {

  };


  class SymbolTableSection : public SectionBase {

+  MAKE_SEC_WRITER_FRIEND

+

  protected:

    std::vector<std::unique_ptr<Symbol>> Symbols;

    StringTableSection *SymbolNames = nullptr;

@@ -218,17 +360,13 @@ public:

    void localize(std::function<bool(const Symbol &)> ToLocalize);

    void initialize(SectionTableRef SecTable) override;

    void finalize() override;

+  void accept(SectionVisitor &Visitor) const override;


    static bool classof(const SectionBase *S) {

      return S->Type == ELF::SHT_SYMTAB;

    }

  };


-// Only writeSection depends on the ELF type so we implement it in a

subclass.

-template <class ELFT> class SymbolTableSectionImpl : public

SymbolTableSection {

-  void writeSection(FileOutputBuffer &Out) const override;

-};

-

  struct Relocation {

    const Symbol *RelocSymbol = nullptr;

    uint64_t Offset;

@@ -275,20 +413,16 @@ public:

    void finalize() override;

  };


-template <class ELFT>

  class RelocationSection

      : public RelocSectionWithSymtabBase<SymbolTableSection> {

-private:

-  using Elf_Rel = typename ELFT::Rel;

-  using Elf_Rela = typename ELFT::Rela;

+  MAKE_SEC_WRITER_FRIEND


+private:

    std::vector<Relocation> Relocations;


-  template <class T> void writeRel(T *Buf) const;

-

  public:

    void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }

-  void writeSection(FileOutputBuffer &Out) const override;

+  void accept(SectionVisitor &Visitor) const override;


    static bool classof(const SectionBase *S) {

      if (S->Flags & ELF::SHF_ALLOC)

@@ -331,13 +465,15 @@ public:


  class DynamicRelocationSection

      : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {

+  MAKE_SEC_WRITER_FRIEND

+

  private:

    ArrayRef<uint8_t> Contents;


  public:

    DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}


-  void writeSection(FileOutputBuffer &Out) const override;

+  void accept(SectionVisitor &) const override;


    static bool classof(const SectionBase *S) {

      if (!(S->Flags & ELF::SHF_ALLOC))

@@ -346,12 +482,10 @@ public:

    }

  };


-template <class ELFT> class GnuDebugLinkSection : public SectionBase {

+class GnuDebugLinkSection : public SectionBase {

+  MAKE_SEC_WRITER_FRIEND

+

  private:

-  // Elf_Word is 4-bytes on every format but has the same endianess as

the elf

-  // type ELFT. We'll need to write the CRC32 out in the proper endianess

so

-  // we'll make sure to use this type.

-  using Elf_Word = typename ELFT::Word;


    StringRef FileName;

    uint32_t CRC32;

@@ -361,92 +495,101 @@ private:

  public:

    // If we add this section from an external source we can use this ctor.

    GnuDebugLinkSection(StringRef File);

-  void writeSection(FileOutputBuffer &Out) const override;

+  void accept(SectionVisitor &Visitor) const override;

  };


-template <class ELFT> class Object {

-private:

-  using SecPtr = std::unique_ptr<SectionBase>;

-  using SegPtr = std::unique_ptr<Segment>;

+class Reader {

+public:

+  virtual ~Reader();

+  virtual std::unique_ptr<Object> create() const = 0;

+};

+

+using object::OwningBinary;

+using object::Binary;

+using object::ELFFile;

+using object::ELFObjectFile;


+template <class ELFT> class ELFBuilder {

+private:

    using Elf_Shdr = typename ELFT::Shdr;

-  using Elf_Ehdr = typename ELFT::Ehdr;

-  using Elf_Phdr = typename ELFT::Phdr;


-  void initSymbolTable(const object::ELFFile<ELFT> &ElfFile,

-                       SymbolTableSection *SymTab, SectionTableRef

SecTable);

-  SecPtr makeSection(const object::ELFFile<ELFT> &ElfFile,

-                     const Elf_Shdr &Shdr);

-  void readProgramHeaders(const object::ELFFile<ELFT> &ElfFile);

-  SectionTableRef readSectionHeaders(const object::ELFFile<ELFT>

&ElfFile);

+  const ELFFile<ELFT> &ElfFile;

+  Object &Obj;


-protected:

-  StringTableSection *SectionNames = nullptr;

-  SymbolTableSection *SymbolTable = nullptr;

-  std::vector<SecPtr> Sections;

-  std::vector<SegPtr> Segments;

-

-  void writeHeader(FileOutputBuffer &Out) const;

-  void writeProgramHeaders(FileOutputBuffer &Out) const;

-  void writeSectionData(FileOutputBuffer &Out) const;

-  void writeSectionHeaders(FileOutputBuffer &Out) const;

+  void readProgramHeaders();

+  void initSymbolTable(SymbolTableSection *SymTab);

+  void readSectionHeaders();

+  SectionBase &makeSection(const Elf_Shdr &Shdr);


  public:

-  uint8_t Ident[16];

-  uint64_t Entry;

-  uint64_t SHOffset;

-  uint32_t Type;

-  uint32_t Machine;

-  uint32_t Version;

-  uint32_t Flags;

-  bool WriteSectionHeaders = true;

-

-  Object(const object::ELFObjectFile<ELFT> &Obj);

-  virtual ~Object() = default;

+  ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj)

+      : ElfFile(*ElfObj.getELFFile()), Obj(Obj) {}


-  SymbolTableSection *getSymTab() const { return SymbolTable; }

-  const SectionBase *getSectionHeaderStrTab() const { return

SectionNames; }

-  void removeSections(std::function<bool(const SectionBase &)> ToRemove);

-  void addSection(StringRef SecName, ArrayRef<uint8_t> Data);

-  void addGnuDebugLink(StringRef File);

-  virtual size_t totalSize() const = 0;

-  virtual void finalize() = 0;

-  virtual void write(FileOutputBuffer &Out) const = 0;

+  void build();

  };


-template <class ELFT> class ELFObject : public Object<ELFT> {

+class ELFReader : public Reader {

  private:

-  using SecPtr = std::unique_ptr<SectionBase>;

-  using SegPtr = std::unique_ptr<Segment>;

-

-  using Elf_Shdr = typename ELFT::Shdr;

-  using Elf_Ehdr = typename ELFT::Ehdr;

-  using Elf_Phdr = typename ELFT::Phdr;

-

-  void sortSections();

-  void assignOffsets();

+  std::unique_ptr<Binary> Binary;



Various compilers don't like using the same name for a class and a member.

I suppose you'll need to rename the member.



Thanks,

--paulr



+  std::shared_ptr<MemoryBuffer> Data;


  public:

-  ELFObject(const object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj)

{}

-

-  void finalize() override;

-  size_t totalSize() const override;

-  void write(FileOutputBuffer &Out) const override;

+  ElfType getElfType() const;

+  std::unique_ptr<Object> create() const override;

+  ELFReader(StringRef File);

  };


-template <class ELFT> class BinaryObject : public Object<ELFT> {

+class Object {

  private:

    using SecPtr = std::unique_ptr<SectionBase>;

    using SegPtr = std::unique_ptr<Segment>;


-  uint64_t TotalSize;

+  std::shared_ptr<MemoryBuffer> OwnedData;

+  std::vector<SecPtr> Sections;

+  std::vector<SegPtr> Segments;


  public:

-  BinaryObject(const object::ELFObjectFile<ELFT> &Obj) :

Object<ELFT>(Obj) {}

+  template <class T>

+  using Range = iterator_range<

+      pointee_iterator<typename

std::vector<std::unique_ptr<T>>::iterator>>;


-  void finalize() override;

-  size_t totalSize() const override;

-  void write(FileOutputBuffer &Out) const override;

+  template <class T>

+  using ConstRange = iterator_range<pointee_iterator<

+      typename std::vector<std::unique_ptr<T>>::const_iterator>>;

+

+  uint8_t Ident[16];

+  uint64_t Entry;

+  uint64_t SHOffset;

+  uint32_t Type;

+  uint32_t Machine;

+  uint32_t Version;

+  uint32_t Flags;

+

+  StringTableSection *SectionNames = nullptr;

+  SymbolTableSection *SymbolTable = nullptr;

+

+  Object(std::shared_ptr<MemoryBuffer> Data) : OwnedData(Data) {}

+  virtual ~Object() = default;

+

+  void sortSections();

+  SectionTableRef sections() { return SectionTableRef(Sections); }

+  ConstRange<SectionBase> sections() const {

+    return make_pointee_range(Sections);

+  }

+  Range<Segment> segments() { return make_pointee_range(Segments); }

+  ConstRange<Segment> segments() const { return

make_pointee_range(Segments); }

+

+  void removeSections(std::function<bool(const SectionBase &)> ToRemove);

+  template <class T, class... Ts> T &addSection(Ts &&... Args) {

+    auto Sec = llvm::make_unique<T>(std::forward<Ts>(Args)...);

+    auto Ptr = Sec.get();

+    Sections.emplace_back(std::move(Sec));

+    return *Ptr;

+  }

+  Segment &addSegment(ArrayRef<uint8_t> Data) {

+    Segments.emplace_back(llvm::make_unique<Segment>(Data));

+    return *Segments.back();

+  }

  };


  } // end namespace llvm


Modified: llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp

URL: https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_tools_llvm-2D&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=Jt__weu8bTTZMmQiRlU2gOsaNTUaBGk2SW-FzUGwoQw&e=

objcopy/llvm-objcopy.cpp?rev=323480&r1=323479&r2=323480&view=diff

==========================================================================

====

--- llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp (original)

+++ llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp Thu Jan 25 14:46:17

2018

@@ -130,42 +130,42 @@ using SectionPred = std::function<bool(c


  bool IsDWOSection(const SectionBase &Sec) { return

Sec.Name.endswith(".dwo"); }


-template <class ELFT>

-bool OnlyKeepDWOPred(const Object<ELFT> &Obj, const SectionBase &Sec) {

+bool OnlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {

    // We can't remove the section header string table.

-  if (&Sec == Obj.getSectionHeaderStrTab())

+  if (&Sec == Obj.SectionNames)

      return false;

    // Short of keeping the string table we want to keep everything that is

a DWO

    // section and remove everything else.

    return !IsDWOSection(Sec);

  }


-template <class ELFT>

-void WriteObjectFile(const Object<ELFT> &Obj, StringRef File) {

-  std::unique_ptr<FileOutputBuffer> Buffer;

-  Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =

-      FileOutputBuffer::create(File, Obj.totalSize(),

-                               FileOutputBuffer::F_executable);

-  handleAllErrors(BufferOrErr.takeError(), [](const ErrorInfoBase &) {

-    error("failed to open " + OutputFilename);

-  });

-  Buffer = std::move(*BufferOrErr);

-

-  Obj.write(*Buffer);

-  if (auto E = Buffer->commit())

-    reportError(File, errorToErrorCode(std::move(E)));

-}

-

-template <class ELFT>

-void SplitDWOToFile(const ELFObjectFile<ELFT> &ObjFile, StringRef File) {

-  // Construct a second output file for the DWO sections.

-  ELFObject<ELFT> DWOFile(ObjFile);

-

-  DWOFile.removeSections([&](const SectionBase &Sec) {

-    return OnlyKeepDWOPred<ELFT>(DWOFile, Sec);

-  });

-  DWOFile.finalize();

-  WriteObjectFile(DWOFile, File);

+static ElfType OutputElfType;

+

+std::unique_ptr<Writer> CreateWriter(Object &Obj, StringRef File) {

+  if (OutputFormat == "binary") {

+    return llvm::make_unique<BinaryWriter>(OutputFilename, Obj);

+  }

+  // Depending on the initial ELFT and OutputFormat we need a different

Writer.

+  switch (OutputElfType) {

+  case ELFT_ELF32LE:

+    return llvm::make_unique<ELFWriter<ELF32LE>>(File, Obj,

!StripSections);

+  case ELFT_ELF64LE:

+    return llvm::make_unique<ELFWriter<ELF64LE>>(File, Obj,

!StripSections);

+  case ELFT_ELF32BE:

+    return llvm::make_unique<ELFWriter<ELF32BE>>(File, Obj,

!StripSections);

+  case ELFT_ELF64BE:

+    return llvm::make_unique<ELFWriter<ELF64BE>>(File, Obj,

!StripSections);

+  }

+  llvm_unreachable("Invalid output format");

+}

+

+void SplitDWOToFile(const Reader &Reader, StringRef File) {

+  auto DWOFile = Reader.create();

+  DWOFile->removeSections(

+      [&](const SectionBase &Sec) { return OnlyKeepDWOPred(*DWOFile,

Sec); });

+  auto Writer = CreateWriter(*DWOFile, File);

+  Writer->finalize();

+  Writer->write();

  }


  // This function handles the high level operations of GNU objcopy

including

@@ -175,23 +175,16 @@ void SplitDWOToFile(const ELFObjectFile<

  // any previous removals. Lastly whether or not something is removed

shouldn't

  // depend a) on the order the options occur in or b) on some opaque

priority

  // system. The only priority is that keeps/copies overrule removes.

-template <class ELFT> void CopyBinary(const ELFObjectFile<ELFT> &ObjFile)

{

-  std::unique_ptr<Object<ELFT>> Obj;

+void HandleArgs(Object &Obj, const Reader &Reader) {


-  if (!OutputFormat.empty() && OutputFormat != "binary")

-    error("invalid output format '" + OutputFormat + "'");

-  if (!OutputFormat.empty() && OutputFormat == "binary")

-    Obj = llvm::make_unique<BinaryObject<ELFT>>(ObjFile);

-  else

-    Obj = llvm::make_unique<ELFObject<ELFT>>(ObjFile);

-

-  if (!SplitDWO.empty())

-    SplitDWOToFile<ELFT>(ObjFile, SplitDWO.getValue());

+  if (!SplitDWO.empty()) {

+    SplitDWOToFile(Reader, SplitDWO);

+  }


    // Localize:


    if (LocalizeHidden) {

-    Obj->getSymTab()->localize([](const Symbol &Sym) {

+    Obj.SymbolTable->localize([](const Symbol &Sym) {

        return Sym.Visibility == STV_HIDDEN || Sym.Visibility ==

STV_INTERNAL;

      });

    }

@@ -214,7 +207,7 @@ template <class ELFT> void CopyBinary(co


    if (ExtractDWO)

      RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {

-      return OnlyKeepDWOPred(*Obj, Sec) || RemovePred(Sec);

+      return OnlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);

      };


    if (StripAllGNU)

@@ -223,7 +216,7 @@ template <class ELFT> void CopyBinary(co

          return true;

        if ((Sec.Flags & SHF_ALLOC) != 0)

          return false;

-      if (&Sec == Obj->getSectionHeaderStrTab())

+      if (&Sec == Obj.SectionNames)

          return false;

        switch (Sec.Type) {

        case SHT_SYMTAB:

@@ -239,7 +232,6 @@ template <class ELFT> void CopyBinary(co

      RemovePred = [RemovePred](const SectionBase &Sec) {

        return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0;

      };

-    Obj->WriteSectionHeaders = false;

    }


    if (StripDebug) {

@@ -252,7 +244,7 @@ template <class ELFT> void CopyBinary(co

      RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {

        if (RemovePred(Sec))

          return true;

-      if (&Sec == Obj->getSectionHeaderStrTab())

+      if (&Sec == Obj.SectionNames)

          return false;

        return (Sec.Flags & SHF_ALLOC) == 0;

      };

@@ -261,7 +253,7 @@ template <class ELFT> void CopyBinary(co

      RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {

        if (RemovePred(Sec))

          return true;

-      if (&Sec == Obj->getSectionHeaderStrTab())

+      if (&Sec == Obj.SectionNames)

          return false;

        if (Sec.Name.startswith(".gnu.warning"))

          return false;

@@ -278,17 +270,15 @@ template <class ELFT> void CopyBinary(co

          return false;


        // Allow all implicit removes.

-      if (RemovePred(Sec)) {

+      if (RemovePred(Sec))

          return true;

-      }


        // Keep special sections.

-      if (Obj->getSectionHeaderStrTab() == &Sec) {

+      if (Obj.SectionNames == &Sec)

          return false;

-      }

-      if (Obj->getSymTab() == &Sec || Obj->getSymTab()->getStrTab() ==

&Sec) {

+      if (Obj.SymbolTable == &Sec || Obj.SymbolTable->getStrTab() ==

&Sec)

          return false;

-      }

+

        // Remove everything else.

        return true;

      };

@@ -305,7 +295,7 @@ template <class ELFT> void CopyBinary(co

      };

    }


-  Obj->removeSections(RemovePred);

+  Obj.removeSections(RemovePred);


    if (!AddSection.empty()) {

      for (const auto &Flag : AddSection) {

@@ -318,16 +308,22 @@ template <class ELFT> void CopyBinary(co

        auto Buf = std::move(*BufOrErr);

        auto BufPtr = reinterpret_cast<const uint8_t *>(Buf-

>getBufferStart());

        auto BufSize = Buf->getBufferSize();

-      Obj->addSection(SecName, ArrayRef<uint8_t>(BufPtr, BufSize));

+      Obj.addSection<OwnedDataSection>(SecName,

+                                       ArrayRef<uint8_t>(BufPtr,

BufSize));

      }

    }


    if (!AddGnuDebugLink.empty()) {

-    Obj->addGnuDebugLink(AddGnuDebugLink);

+    Obj.addSection<GnuDebugLinkSection>(StringRef(AddGnuDebugLink));

    }

+}


-  Obj->finalize();

-  WriteObjectFile(*Obj, OutputFilename.getValue());

+std::unique_ptr<Reader> CreateReader() {

+  // Right now we can only read ELF files so there's only one reader;

+  auto Out = llvm::make_unique<ELFReader>(StringRef(InputFilename));

+  // We need to set the default ElfType for output.

+  OutputElfType = Out->getElfType();

+  return std::move(Out);

  }


  int main(int argc, char **argv) {

@@ -341,25 +337,11 @@ int main(int argc, char **argv) {

      cl::PrintHelpMessage();

      return 2;

    }

-  Expected<OwningBinary<Binary>> BinaryOrErr =

createBinary(InputFilename);

-  if (!BinaryOrErr)

-    reportError(InputFilename, BinaryOrErr.takeError());

-  Binary &Binary = *BinaryOrErr.get().getBinary();

-  if (auto *o = dyn_cast<ELFObjectFile<ELF64LE>>(&Binary)) {

-    CopyBinary(*o);

-    return 0;

-  }

-  if (auto *o = dyn_cast<ELFObjectFile<ELF32LE>>(&Binary)) {

-    CopyBinary(*o);

-    return 0;

-  }

-  if (auto *o = dyn_cast<ELFObjectFile<ELF64BE>>(&Binary)) {

-    CopyBinary(*o);

-    return 0;

-  }

-  if (auto *o = dyn_cast<ELFObjectFile<ELF32BE>>(&Binary)) {

-    CopyBinary(*o);

-    return 0;

-  }

-  reportError(InputFilename, object_error::invalid_file_type);

+

+  auto Reader = CreateReader();

+  auto Obj = Reader->create();

+  auto Writer = CreateWriter(*Obj, OutputFilename);

+  HandleArgs(*Obj, *Reader);

+  Writer->finalize();

+  Writer->write();

  }


Modified: llvm/trunk/tools/llvm-objcopy/llvm-objcopy.h

URL: https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_tools_llvm-2D&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=Jt__weu8bTTZMmQiRlU2gOsaNTUaBGk2SW-FzUGwoQw&e=

objcopy/llvm-objcopy.h?rev=323480&r1=323479&r2=323480&view=diff

==========================================================================

====

--- llvm/trunk/tools/llvm-objcopy/llvm-objcopy.h (original)

+++ llvm/trunk/tools/llvm-objcopy/llvm-objcopy.h Thu Jan 25 14:46:17 2018

@@ -19,6 +19,9 @@

  namespace llvm {


  LLVM_ATTRIBUTE_NORETURN extern void error(Twine Message);

+LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, Error E);

+LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File,

+                                                std::error_code EC);


  // This is taken from llvm-readobj.

  // [see here](llvm/tools/llvm-readobj/llvm-readobj.h:38)



_______________________________________________

llvm-commits mailing list

llvm-commits at lists.llvm.org<mailto:llvm-commits at lists.llvm.org>

https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.llvm.org_cgi-2Dbin_mailman_listinfo_llvm-2Dcommits&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=EssJFIPRsDXneVP3lF1TU1YQElYePCqcvoueiN0Rdz8&e=

_______________________________________________
llvm-commits mailing list
llvm-commits at lists.llvm.org<mailto:llvm-commits at lists.llvm.org>
https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.llvm.org_cgi-2Dbin_mailman_listinfo_llvm-2Dcommits&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=o3kDXzdBUE3ljQXKeTWOMw&m=axCDusFjx_5KEwc1LSTJ5O-wHSLNALxvWFSQV77APPo&s=EssJFIPRsDXneVP3lF1TU1YQElYePCqcvoueiN0Rdz8&e=

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180126/364ff92d/attachment-0001.html>


More information about the llvm-commits mailing list