added support -output-binary; some work might be best taken out though
diff --git a/test/tools/llvm-objcopy/basic-binary-copy.s b/test/tools/llvm-objcopy/basic-binary-copy.s
new file mode 100644
index 0000000..380678a
--- /dev/null
+++ b/test/tools/llvm-objcopy/basic-binary-copy.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objcopy -output-binary %t %t2
+# RUN: od -t x2 -v %t2 | FileCheck %s
+# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE
+
+  .globl main
+  .text
+main:
+  ret
+  ret
+  ret
+  ret
+
+# CHECK: 0000000 c3c3 c3c3
+# SIZE:  4
diff --git a/test/tools/llvm-objcopy/binary-align-copy.s b/test/tools/llvm-objcopy/binary-align-copy.s
new file mode 100644
index 0000000..faf3ee2
--- /dev/null
+++ b/test/tools/llvm-objcopy/binary-align-copy.s
@@ -0,0 +1,22 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objcopy -output-binary %t %t2
+# RUN: od -t x2 %t2 | FileCheck %s
+# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE
+
+  .globl main
+  .text
+main:
+  ret
+  ret
+  ret
+  ret
+
+  .data
+  .byte 50
+
+# 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/interstitial-binary-copy.s b/test/tools/llvm-objcopy/interstitial-binary-copy.s
new file mode 100644
index 0000000..92f09b7
--- /dev/null
+++ b/test/tools/llvm-objcopy/interstitial-binary-copy.s
@@ -0,0 +1,25 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: printf %4092s | dd of=%t bs=1 seek=4100 conv=notrunc
+# RUN: printf "\x00\x10" | dd of=%t bs=1 seek=208 conv=notrunc
+# RUN: printf "\x00\x10" | dd of=%t bs=1 seek=216 conv=notrunc
+# RUN: llvm-objcopy -output-binary %t %t2
+# RUN: od -t x2 %t2 | FileCheck %s
+# RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE
+
+  .globl main
+  .text
+main:
+  ret
+  ret
+  ret
+  ret
+
+  .data
+  .byte 50
+
+# CHECK:       0000000 c3c3 c3c3 2020 2020 2020 2020 2020 2020
+# CHECK-NEXT:  0000020 2020 2020 2020 2020 2020 2020 2020 2020
+# CHECK-NEXT:  *
+# CHECK-NEXT:  0010000 0032
+# SIZE:        4097
diff --git a/tools/llvm-objcopy/Object.cpp b/tools/llvm-objcopy/Object.cpp
index 6f92aa3..10cd25c 100644
--- a/tools/llvm-objcopy/Object.cpp
+++ b/tools/llvm-objcopy/Object.cpp
@@ -13,9 +13,13 @@
 using namespace object;
 using namespace ELF;
 
-template <class ELFT> void Segment::writeHeader(FileOutputBuffer &Out) const {
-  uint8_t *Buf = Out.getBufferStart();
-  Buf += sizeof(typename ELFT::Ehdr) + Index * sizeof(typename ELFT::Phdr);
+uint64_t align(uint64_t Value, uint64_t Multiple) {
+  if (!Multiple || Value % Multiple == 0)
+    return Value;
+  return Value + Multiple - Value % Multiple;
+}
+
+template <class ELFT> void Segment::writeHeader(uint8_t *Buf) const {
   typename ELFT::Phdr &Phdr = *reinterpret_cast<typename ELFT::Phdr *>(Buf);
   Phdr.p_type = Type;
   Phdr.p_flags = Flags;
@@ -28,24 +32,60 @@
 }
 
 void Segment::finalize() {
-  auto MinElem =
-      std::min_element(std::begin(Sections), std::end(Sections),
-                       [](const SectionBase *a, const SectionBase *b) -> bool {
-                         return a->Offset < b->Offset;
-                       });
-  Offset = (**MinElem).Offset;
-  FileSize = 0;
-  for (auto Section : Sections)
-    if (Section->Type != SHT_NOBITS)
-      FileSize += Section->Size;
+  auto MinElem = firstSection();
+  if (!MinElem)
+    return;
+  if (Type == PT_LOAD) {
+    auto PrevSection = MinElem;
+    for (auto Sec : Sections) {
+      if (Sec->Addr > PrevSection->Addr + PrevSection->Size) {
+        // Then we have a gap which we can expect file layout to respect. We
+        // need to respect the contents of this gap as well as the user may have
+        // put something meanigful in them like trap instructions in the case
+        // that this segment is executable.
+        ArrayRef<uint8_t> InterstitialData{Contents.data() + PrevSection->Addr -
+                                               VAddr + PrevSection->Size,
+                                           Contents.data() + Sec->Addr - VAddr};
+        auto InterstitialSection = new Section(InterstitialData);
+        InterstitialSection->Addr = PrevSection->Addr + PrevSection->Size;
+        InterstitialSections.emplace_back(InterstitialSection);
+      }
+      PrevSection = Sec;
+    }
+    // Lastly there might be an interstitial gap between the last section and
+    // the end of the segment.
+    if (VAddr + MemSize > PrevSection->Addr + PrevSection->Size) {
+      ArrayRef<uint8_t> InterstitialData{Contents.data() + PrevSection->Addr -
+                                             VAddr + PrevSection->Size,
+                                         Contents.data() + MemSize};
+      auto InterstitialSection = new Section(InterstitialData);
+      InterstitialSection->Addr = PrevSection->Addr + PrevSection->Size;
+      InterstitialSections.emplace_back(InterstitialSection);
+    }
+    for (auto &InterstitialSection : InterstitialSections)
+      Sections.insert(InterstitialSection.get());
+  }
+
+  // In practice you could have a section that contained no sections. In this
+  // case the file offset is meaingless. Other aspects of it can still hold
+  // meaning however so we want to preserve those things still. So if there is
+  // no MinElem we just leave Offset as it was in the file.
+  if (MinElem)
+    Offset = MinElem->Offset;
+}
+
+void Segment::writeMemSegment(uint8_t *Buf) const {
+  // Because we have filled in all gaps with interstitial sections we can be
+  // sure that we will cover the entire size of MemSize
+  for (auto Section : Sections) {
+    Section->writeSection(Buf);
+    Buf += Section->Size;
+  }
 }
 
 void SectionBase::finalize() {}
 
-template <class ELFT>
-void SectionBase::writeHeader(FileOutputBuffer &Out) const {
-  uint8_t *Buf = Out.getBufferStart();
-  Buf += HeaderOffset;
+template <class ELFT> void SectionBase::writeHeader(uint8_t *Buf) const {
   typename ELFT::Shdr &Shdr = *reinterpret_cast<typename ELFT::Shdr *>(Buf);
   Shdr.sh_name = NameIndex;
   Shdr.sh_type = Type;
@@ -59,8 +99,7 @@
   Shdr.sh_entsize = EntrySize;
 }
 
-void Section::writeSection(FileOutputBuffer &Out) const {
-  uint8_t *Buf = Out.getBufferStart() + Offset;
+void Section::writeSection(uint8_t *Buf) const {
   std::copy(std::begin(Contents), std::end(Contents), Buf);
 }
 
@@ -93,8 +132,7 @@
   }
 }
 
-void StringTableSection::writeSection(FileOutputBuffer &Out) const {
-  uint8_t *Buf = Out.getBufferStart() + Offset;
+void StringTableSection::writeSection(uint8_t *Buf) const {
   for (const auto &Name : Strings) {
     Buf = std::copy(std::begin(Name.getKey()), std::end(Name.getKey()), Buf);
     // We need to set the null character and then increment the buffer past it
@@ -156,9 +194,7 @@
 }
 
 template <class ELFT>
-void SymbolTableSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const {
-  uint8_t *Buf = Out.getBufferStart();
-  Buf += Offset;
+void SymbolTableSection<ELFT>::writeSection(uint8_t *Buf) const {
   typename ELFT::Sym *Sym = reinterpret_cast<typename ELFT::Sym *>(Buf);
 
   for(auto &Symbol : FinalSymbols) {
@@ -176,10 +212,11 @@
 }
 
 template <class ELFT>
-void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
+void ObjectCopyBase<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
   uint32_t Index = 0;
   for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {
-    Segments.emplace_back();
+    ArrayRef<uint8_t> Data{ElfFile.base() + Phdr.p_offset, Phdr.p_filesz};
+    Segments.emplace_back(Data);
     Segment &Seg = Segments.back();
     Seg.Type = Phdr.p_type;
     Seg.Flags = Phdr.p_flags;
@@ -191,17 +228,18 @@
     Seg.Index = Index++;
     for (auto &Section : Sections) {
       if (Seg.Offset <= Section->Offset &&
-          Seg.Offset + Seg.FileSize >= Section->Offset + Section->Size) {
-        Seg.addSection(&*Section);
+          Seg.Offset + Seg.FileSize >= Section->Offset + Section->Size &&
+          (Section->Flags & SHF_ALLOC)) {
         Section->ParrentSegment = &Seg;
+        Seg.addSection(Section.get());
       }
     }
   }
 }
 
 template <class ELFT>
-void Object<ELFT>::readSymbolTable(const ELFFile<ELFT> &ElfFile,
-                                   const Elf_Shdr &SymTabShdr) {
+void ObjectCopyBase<ELFT>::readSymbolTable(const ELFFile<ELFT> &ElfFile,
+                                           const Elf_Shdr &SymTabShdr) {
 
   StringTableSection *StrTab =
       dyn_cast<StringTableSection>(Sections[SymTabShdr.sh_link].get());
@@ -238,7 +276,7 @@
 }
 
 template <class ELFT>
-void Object<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
+void ObjectCopyBase<ELFT>::readSectionHeaders(const ELFFile<ELFT> &ElfFile) {
   uint32_t Index = 0;
   const Elf_Shdr *SymTabShdr = nullptr;
   for (const auto &Shdr : unwrapOrError(ElfFile.sections())) {
@@ -277,13 +315,8 @@
     readSymbolTable(ElfFile, *SymTabShdr);
 }
 
-template <class ELFT> size_t Object<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;
-  return SHOffset + Sections.size() * sizeof(Elf_Shdr);
-}
-
-template <class ELFT> Object<ELFT>::Object(const ELFObjectFile<ELFT> &Obj) {
+template <class ELFT>
+ObjectCopyBase<ELFT>::ObjectCopyBase(const ELFObjectFile<ELFT> &Obj) {
   const auto &ElfFile = *Obj.getELFFile();
   const auto &Ehdr = *ElfFile.getHeader();
 
@@ -304,31 +337,33 @@
   readProgramHeaders(ElfFile);
 }
 
-template <class ELFT> void Object<ELFT>::sortSections() {
+template <class ELFT> size_t ObjectCopyELF<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;
+  return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr);
+}
+
+template <class ELFT> void ObjectCopyELF<ELFT>::sortSections() {
   std::sort(
-      std::begin(Sections), std::end(Sections),
+      std::begin(this->Sections), std::end(this->Sections),
       [](const SecPtr &A, const SecPtr &B) { return A->Index < B->Index; });
 }
 
-uint64_t align(uint64_t Value, uint64_t Multiple) {
-  if (!Multiple || Value % Multiple == 0)
-    return Value;
-  return Value + Multiple - Value % Multiple;
-}
-
-template <class ELFT> void Object<ELFT>::assignOffsets() {
+template <class ELFT> void ObjectCopyELF<ELFT>::assignOffsets() {
   // Decide file offsets and indexs
-  size_t PhdrSize = Segments.size() * sizeof(Elf_Phdr);
+  size_t PhdrSize = this->Segments.size() * sizeof(Elf_Phdr);
   // After the header and the program headers we can put section data.
   uint64_t Offset = sizeof(Elf_Ehdr) + PhdrSize;
   uint64_t Index = 0;
-  for (auto &Section : Sections) {
+  for (auto &Section : this->Sections) {
     // The segment can have a different alignment than the section. We need to
     // make sure
     if (Section->ParrentSegment) {
       auto FirstInSeg = Section->ParrentSegment->firstSection();
       if (FirstInSeg == Section.get())
         Offset = align(Offset, Section->ParrentSegment->Align);
+      // We should respect interstitial gaps of allocated sections
+      Offset = FirstInSeg->Offset + Section->Addr - FirstInSeg->Addr;
     }
     Offset = align(Offset, Section->Align);
     Section->Offset = Offset;
@@ -341,77 +376,119 @@
   // section header table offset to be exactly here. This spot might not be
   // aligned properlly however so we should align it as needed. This only takes
   // a little bit of tweaking to ensure that the sh_name is 4 byte aligned
-  Offset = align(Offset, 4);
-  SHOffset = Offset;
+  Offset = align(Offset, sizeof(typename ELFT::Word));
+  this->SHOffset = Offset;
 }
 
-template <class ELFT> void Object<ELFT>::finalize() {
+template <class ELFT> void ObjectCopyELF<ELFT>::finalize() {
   sortSections();
   assignOffsets();
 
   // finalize SectionNames first so that we can assign name indexes.
-  SectionNames->finalize();
+  this->SectionNames->finalize();
 
   // Finally now that all offsets and indexes have been set we can finalize any
   // reamining issues.
-  uint64_t Offset = SHOffset;
-  for (auto &Section : Sections) {
-    Section->HeaderOffset = Offset;
-    Offset += sizeof(Elf_Shdr);
-    Section->NameIndex = SectionNames->findIndex(Section->Name);
+  for (auto &Section : this->Sections) {
+    Section->NameIndex = this->SectionNames->findIndex(Section->Name);
     Section->finalize();
   }
 
-  for (auto &Segment : Segments)
+  for (auto &Segment : this->Segments)
     Segment.finalize();
 }
 
 template <class ELFT>
-void Object<ELFT>::writeHeader(FileOutputBuffer &Out) const {
+void ObjectCopyELF<ELFT>::writeHeader(FileOutputBuffer &Out) const {
   uint8_t *Buf = Out.getBufferStart();
   typename ELFT::Ehdr &Ehdr = *reinterpret_cast<typename ELFT::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(this->Ident, this->Ident + 16, Ehdr.e_ident);
+  Ehdr.e_type = this->Type;
+  Ehdr.e_machine = this->Machine;
+  Ehdr.e_version = this->Version;
+  Ehdr.e_entry = this->Entry;
   Ehdr.e_phoff = sizeof(Elf_Ehdr);
-  Ehdr.e_shoff = SHOffset;
-  Ehdr.e_flags = Flags;
+  Ehdr.e_shoff = this->SHOffset;
+  Ehdr.e_flags = this->Flags;
   Ehdr.e_ehsize = sizeof(Elf_Ehdr);
   Ehdr.e_phentsize = sizeof(Elf_Phdr);
-  Ehdr.e_phnum = Segments.size();
+  Ehdr.e_phnum = this->Segments.size();
   Ehdr.e_shentsize = sizeof(Elf_Shdr);
-  Ehdr.e_shnum = Sections.size();
-  Ehdr.e_shstrndx = SectionNames->Index;
+  Ehdr.e_shnum = this->Sections.size();
+  Ehdr.e_shstrndx = this->SectionNames->Index;
 }
 
 template <class ELFT>
-void Object<ELFT>::writeProgramHeaders(FileOutputBuffer &Out) const {
-  for (auto &Phdr : Segments)
-    Phdr.template writeHeader<ELFT>(Out);
+void ObjectCopyELF<ELFT>::writeProgramHeaders(FileOutputBuffer &Out) const {
+  uint8_t *Buf = Out.getBufferStart() + sizeof(Elf_Ehdr);
+  for (auto &Segment : this->Segments) {
+    Segment.template writeHeader<ELFT>(Buf);
+    Buf += sizeof(Elf_Phdr);
+  }
 }
 
 template <class ELFT>
-void Object<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {
-  for (auto &Section : Sections)
-    Section->template writeHeader<ELFT>(Out);
+void ObjectCopyELF<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {
+  uint8_t *Buf = Out.getBufferStart() + this->SHOffset;
+  for (auto &Section : this->Sections) {
+    Section->template writeHeader<ELFT>(Buf);
+    Buf += sizeof(Elf_Shdr);
+  }
 }
 
 template <class ELFT>
-void Object<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
-  for (auto &Section : Sections)
-    Section->writeSection(Out);
+void ObjectCopyELF<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
+  uint8_t *Buf = Out.getBufferStart();
+  for (auto &Section : this->Sections) {
+    Section->writeSection(Buf + Section->Offset);
+  }
 }
 
-template <class ELFT> void Object<ELFT>::write(FileOutputBuffer &Out) {
+template <class ELFT>
+void ObjectCopyELF<ELFT>::write(FileOutputBuffer &Out) const {
   writeHeader(Out);
   writeProgramHeaders(Out);
   writeSectionData(Out);
   writeSectionHeaders(Out);
 }
 
-template class Object<ELF64LE>;
-template class Object<ELF64BE>;
-template class Object<ELF32LE>;
-template class Object<ELF32BE>;
+template <class ELFT> void ObjectCopyBinary<ELFT>::finalize() {
+  for (auto &Segment : this->Segments)
+    Segment.finalize();
+}
+
+template <class ELFT> size_t ObjectCopyBinary<ELFT>::totalSize() const {
+  uint64_t BinSize = 0;
+  for (auto &Segment : this->Segments) {
+    if (Segment.Type == PT_LOAD && Segment.Offset != 0) {
+      BinSize = align(BinSize, Segment.Align);
+      BinSize += Segment.FileSize;
+    }
+  }
+  return BinSize;
+}
+
+template <class ELFT>
+void ObjectCopyBinary<ELFT>::write(FileOutputBuffer &Out) const {
+  // It's worth noting that Segments might be put in very different locations
+  // from each other. They will still be placed
+  uint8_t *Buf = Out.getBufferStart();
+  uint64_t Offset = 0;
+  for (auto &Segment : this->Segments) {
+    if (Segment.Type == PT_LOAD && Segment.Offset != 0) {
+      Offset = align(Offset, Segment.Align);
+      Segment.writeMemSegment(Buf + Offset);
+      Offset += Segment.FileSize;
+    }
+  }
+}
+
+template class ObjectCopyELF<ELF64LE>;
+template class ObjectCopyELF<ELF64BE>;
+template class ObjectCopyELF<ELF32LE>;
+template class ObjectCopyELF<ELF32BE>;
+
+template class ObjectCopyBinary<ELF64LE>;
+template class ObjectCopyBinary<ELF64BE>;
+template class ObjectCopyBinary<ELF32LE>;
+template class ObjectCopyBinary<ELF32BE>;
diff --git a/tools/llvm-objcopy/Object.h b/tools/llvm-objcopy/Object.h
index aba0c26..fcf143a 100644
--- a/tools/llvm-objcopy/Object.h
+++ b/tools/llvm-objcopy/Object.h
@@ -27,8 +27,7 @@
 class SectionBase {
 public:
   llvm::StringRef Name;
-  Segment* ParrentSegment;
-  uint64_t HeaderOffset;
+  Segment *ParrentSegment = nullptr;
   uint32_t Index;
 
   uint64_t Addr = 0;
@@ -44,8 +43,8 @@
 
   virtual ~SectionBase() {}
   virtual void finalize();
-  template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const;
-  virtual void writeSection(llvm::FileOutputBuffer &Out) const = 0;
+  template <class ELFT> void writeHeader(uint8_t *Buf) const;
+  virtual void writeSection(uint8_t *Buf) const = 0;
 };
 
 class Segment {
@@ -57,6 +56,8 @@
   };
 
   std::set<const SectionBase *, SectionCompare> Sections;
+  std::vector<std::unique_ptr<SectionBase>> InterstitialSections;
+  llvm::ArrayRef<uint8_t> Contents;
 
 public:
   uint64_t Align;
@@ -68,6 +69,7 @@
   uint64_t Type;
   uint64_t VAddr;
 
+  Segment(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
   void finalize();
   const SectionBase * firstSection() const {
     if(Sections.size())
@@ -75,7 +77,8 @@
     return nullptr;
   }
   void addSection(const SectionBase *sec) { Sections.insert(sec); }
-  template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const;
+  void writeMemSegment(uint8_t *Buf) const;
+  template <class ELFT> void writeHeader(uint8_t *Buf) const;
 };
 
 class Section : public SectionBase {
@@ -83,8 +86,8 @@
   llvm::ArrayRef<uint8_t> Contents;
 
 public:
-  Section(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
-  void writeSection(llvm::FileOutputBuffer &Out) const override;
+  Section(llvm::ArrayRef<uint8_t> Data) : Contents(Data) { Size = Data.size(); }
+  void writeSection(uint8_t *Buf) const override;
 };
 
 class StringTableSection : public SectionBase {
@@ -100,7 +103,7 @@
   void removeString(llvm::StringRef Name);
   uint32_t findIndex(llvm::StringRef Name) const;
   void finalize() override;
-  void writeSection(llvm::FileOutputBuffer &Out) const override;
+  void writeSection(uint8_t *Buf) const override;
   static bool classof(const SectionBase *S) {
     return S->Type == llvm::ELF::SHT_STRTAB;
   }
@@ -136,15 +139,14 @@
                  SectionBase *DefinedIn, uint64_t Value, uint64_t Sz);
   void removeSymbol(llvm::StringRef);
   void finalize() override;
-  void writeSection(llvm::FileOutputBuffer &) const override;
+  void writeSection(uint8_t *Buf) const override;
   static bool classof(const SectionBase *S) {
     return S->Type == llvm::ELF::SHT_SYMTAB;
   }
 };
 
-template<class ELFT>
-class Object {
-private:
+template <class ELFT> class ObjectCopyBase {
+protected:
   typedef std::unique_ptr<SectionBase> SecPtr;
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::Ehdr Elf_Ehdr;
@@ -155,16 +157,11 @@
   std::vector<SecPtr> Sections;
   std::vector<Segment> Segments;
 
-  void sortSections();
-  void assignOffsets();
+private:
   void readProgramHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
   void readSectionHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
   void readSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
                        const Elf_Shdr &SymTabShdr);
-  void writeHeader(llvm::FileOutputBuffer &Out) const;
-  void writeProgramHeaders(llvm::FileOutputBuffer &Out) const;
-  void writeSectionData(llvm::FileOutputBuffer &Out) const;
-  void writeSectionHeaders(llvm::FileOutputBuffer &Out) const;
 
 public:
   uint8_t Ident[16];
@@ -175,9 +172,42 @@
   uint32_t Version;
   uint32_t Flags;
 
-  Object(const llvm::object::ELFObjectFile<ELFT> &Obj);
-  size_t totalSize() const;
-  void finalize();
-  void write(llvm::FileOutputBuffer &Out);
+  ObjectCopyBase(const llvm::object::ELFObjectFile<ELFT> &Obj);
+
+  virtual size_t totalSize() const = 0;
+  virtual void finalize() = 0;
+  virtual void write(llvm::FileOutputBuffer &Out) const = 0;
+  virtual ~ObjectCopyBase() {}
+};
+
+template <class ELFT> class ObjectCopyELF : public ObjectCopyBase<ELFT> {
+private:
+  typedef std::unique_ptr<SectionBase> SecPtr;
+  typedef typename ELFT::Shdr Elf_Shdr;
+  typedef typename ELFT::Ehdr Elf_Ehdr;
+  typedef typename ELFT::Phdr Elf_Phdr;
+
+  void sortSections();
+  void assignOffsets();
+  void writeHeader(llvm::FileOutputBuffer &Out) const;
+  void writeProgramHeaders(llvm::FileOutputBuffer &Out) const;
+  void writeSectionData(llvm::FileOutputBuffer &Out) const;
+  void writeSectionHeaders(llvm::FileOutputBuffer &Out) const;
+
+public:
+  ObjectCopyELF(const llvm::object::ELFObjectFile<ELFT> &Obj)
+      : ObjectCopyBase<ELFT>(Obj) {}
+  virtual size_t totalSize() const override;
+  virtual void finalize() override;
+  virtual void write(llvm::FileOutputBuffer &Out) const override;
+};
+
+template <class ELFT> class ObjectCopyBinary : public ObjectCopyBase<ELFT> {
+public:
+  ObjectCopyBinary(const llvm::object::ELFObjectFile<ELFT> &Obj)
+      : ObjectCopyBase<ELFT>(Obj) {}
+  virtual size_t totalSize() const override;
+  virtual void finalize() override;
+  virtual 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 6a74a8c..a0006f4 100644
--- a/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -50,12 +50,20 @@
 cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>"));
 cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"),
                                     cl::init("-"));
+cl::opt<bool> OutputBinary("output-binary", cl::desc("output raw binary"));
+
 void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) {
   std::unique_ptr<FileOutputBuffer> Buffer;
-  Object<ELF64LE> Obj{ObjFile};
-  Obj.finalize();
+  std::unique_ptr<ObjectCopyBase<ELF64LE>> ObjCopy;
+
+  if (OutputBinary)
+    ObjCopy.reset(new ObjectCopyBinary<ELF64LE>(ObjFile));
+  else
+    ObjCopy.reset(new ObjectCopyELF<ELF64LE>(ObjFile));
+  ObjCopy->finalize();
+
   ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
-      FileOutputBuffer::create(OutputFilename, Obj.totalSize(),
+      FileOutputBuffer::create(OutputFilename, ObjCopy->totalSize(),
                                FileOutputBuffer::F_executable);
   if (auto EC = BufferOrErr.getError())
     error("failed to open " + OutputFilename);
@@ -67,7 +75,8 @@
   if (EC)
     report_fatal_error(EC.message());
   // now if the program fails for any reason the output file will be deleted
-  Obj.write(*Buffer);
+  ObjCopy->write(*Buffer);
+
   if (auto EC = Buffer->commit())
     reportError(OutputFilename, EC);
   Out->keep();