Reland "[llvm][llvm-objcopy] Added support for outputting to binary in llvm-objcopy"

This change adds the "-O binary" flag which directs llvm-objcopy to
output the object file to the same format as GNU objcopy does when given
the flag "-O binary". This was done by splitting the Object class into
two subclasses ObjectELF and ObjectBianry which each output a different
format but relay on the same code to read in the Object in Object.

Patch by Jake Ehrlich

Differential Revision: https://reviews.llvm.org/D34480

llvm-svn: 310127
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index 09edc4c..9b23395 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -53,13 +53,23 @@
 cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>"));
 cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"),
                                     cl::init("-"));
+cl::opt<std::string>
+    OutputFormat("O", cl::desc("set output format to one of the following:"
+                               "\n\tbinary"));
 
 void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) {
   std::unique_ptr<FileOutputBuffer> Buffer;
-  Object<ELF64LE> Obj{ObjFile};
-  Obj.finalize();
+  std::unique_ptr<Object<ELF64LE>> Obj;
+  if (!OutputFormat.empty() && OutputFormat != "binary")
+    error("invalid output format '" + OutputFormat + "'");
+
+  if (!OutputFormat.empty() && OutputFormat == "binary")
+    Obj = llvm::make_unique<BinaryObject<ELF64LE>>(ObjFile);
+  else
+    Obj = llvm::make_unique<ELFObject<ELF64LE>>(ObjFile);
+  Obj->finalize();
   ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
-      FileOutputBuffer::create(OutputFilename, Obj.totalSize(),
+      FileOutputBuffer::create(OutputFilename, Obj->totalSize(),
                                FileOutputBuffer::F_executable);
   if (BufferOrErr.getError())
     error("failed to open " + OutputFilename);
@@ -68,7 +78,7 @@
   std::error_code EC;
   if (EC)
     report_fatal_error(EC.message());
-  Obj.write(*Buffer);
+  Obj->write(*Buffer);
   if (auto EC = Buffer->commit())
     reportError(OutputFilename, EC);
 }