[llvm] r345217 - [llvm-objcopy] Introduce dispatch mechanism based on the input

Alexander Shaposhnikov via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 24 15:49:06 PDT 2018


Author: alexshap
Date: Wed Oct 24 15:49:06 2018
New Revision: 345217

URL: http://llvm.org/viewvc/llvm-project?rev=345217&view=rev
Log:
[llvm-objcopy] Introduce dispatch mechanism based on the input

In this diff we introduce dispatch mechanism based on 
the type of the input (archive, object file, raw binary) 
and the format (coff, elf, macho).
We also move the ELF-specific code into the namespace llvm::objcopy::elf.

Test plan: make check-all

Differential revision: https://reviews.llvm.org/D53311

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

Modified: llvm/trunk/tools/llvm-objcopy/Object.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/Object.cpp?rev=345217&r1=345216&r2=345217&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/Object.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/Object.cpp Wed Oct 24 15:49:06 2018
@@ -28,8 +28,10 @@
 #include <utility>
 #include <vector>
 
-using namespace llvm;
-using namespace llvm::objcopy;
+namespace llvm {
+namespace objcopy {
+namespace elf {
+
 using namespace object;
 using namespace ELF;
 
@@ -1165,7 +1167,9 @@ template <class ELFT> void ELFWriter<ELF
   Ehdr.e_machine = Obj.Machine;
   Ehdr.e_version = Obj.Version;
   Ehdr.e_entry = Obj.Entry;
-  Ehdr.e_phnum = size(Obj.segments());
+  // We have to use the fully-qualified name llvm::size
+  // since some compilers complain on ambiguous resolution.
+  Ehdr.e_phnum = llvm::size(Obj.segments());
   Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
   Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;
   Ehdr.e_flags = Obj.Flags;
@@ -1597,9 +1601,6 @@ void BinaryWriter::finalize() {
   SecWriter = llvm::make_unique<BinarySectionWriter>(Buf);
 }
 
-namespace llvm {
-namespace objcopy {
-
 template class BinaryELFBuilder<ELF64LE>;
 template class BinaryELFBuilder<ELF64BE>;
 template class BinaryELFBuilder<ELF32LE>;
@@ -1614,5 +1615,7 @@ template class ELFWriter<ELF64LE>;
 template class ELFWriter<ELF64BE>;
 template class ELFWriter<ELF32LE>;
 template class ELFWriter<ELF32BE>;
+
+} // end namespace elf
 } // end namespace objcopy
 } // end namespace llvm

Modified: llvm/trunk/tools/llvm-objcopy/Object.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/Object.h?rev=345217&r1=345216&r2=345217&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/Object.h (original)
+++ llvm/trunk/tools/llvm-objcopy/Object.h Wed Oct 24 15:49:06 2018
@@ -30,6 +30,7 @@
 namespace llvm {
 enum class DebugCompressionType;
 namespace objcopy {
+namespace elf {
 
 class SectionBase;
 class Section;
@@ -765,6 +766,8 @@ public:
     return *Segments.back();
   }
 };
+
+} // end namespace elf
 } // end namespace objcopy
 } // end namespace llvm
 

Modified: llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp?rev=345217&r1=345216&r2=345217&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp Wed Oct 24 15:49:06 2018
@@ -53,13 +53,6 @@
 #include <system_error>
 #include <utility>
 
-using namespace llvm;
-using namespace llvm::objcopy;
-using namespace object;
-using namespace ELF;
-
-using SectionPred = std::function<bool(const SectionBase &Sec)>;
-
 namespace llvm {
 namespace objcopy {
 
@@ -92,6 +85,16 @@ LLVM_ATTRIBUTE_NORETURN void reportError
 } // end namespace objcopy
 } // end namespace llvm
 
+// TODO: move everything enclosed in the namespace llvm::objcopy::elf
+// into separate header+cpp files.
+namespace llvm {
+namespace objcopy {
+namespace elf {
+
+using namespace object;
+using namespace ELF;
+using SectionPred = std::function<bool(const SectionBase &Sec)>;
+
 static bool isDebugSection(const SectionBase &Sec) {
   return StringRef(Sec.Name).startswith(".debug") ||
          StringRef(Sec.Name).startswith(".zdebug") || Sec.Name == ".gdb_index";
@@ -513,18 +516,39 @@ static void handleArgs(const CopyConfig
     Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink);
 }
 
-static void executeElfObjcopyOnBinary(const CopyConfig &Config, Reader &Reader,
-                                      Buffer &Out, ElfType OutputElfType) {
+void executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
+                               Buffer &Out) {
+  BinaryReader Reader(Config.BinaryArch, &In);
   std::unique_ptr<Object> Obj = Reader.create();
 
+  const ElfType OutputElfType = getOutputElfType(Config.BinaryArch);
   handleArgs(Config, *Obj, Reader, OutputElfType);
+  std::unique_ptr<Writer> Writer =
+      createWriter(Config, *Obj, Out, OutputElfType);
+  Writer->finalize();
+  Writer->write();
+}
 
+void executeObjcopyOnBinary(const CopyConfig &Config,
+                            object::ELFObjectFileBase &In, Buffer &Out) {
+  ELFReader Reader(&In);
+  std::unique_ptr<Object> Obj = Reader.create();
+  const ElfType OutputElfType = getOutputElfType(In);
+  handleArgs(Config, *Obj, Reader, OutputElfType);
   std::unique_ptr<Writer> Writer =
       createWriter(Config, *Obj, Out, OutputElfType);
   Writer->finalize();
   Writer->write();
 }
 
+} // end namespace elf
+} // end namespace objcopy
+} // end namespace llvm
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::objcopy;
+
 // For regular archives this function simply calls llvm::writeArchive,
 // For thin archives it writes the archive file itself as well as its members.
 static Error deepWriteArchive(StringRef ArcName,
@@ -554,8 +578,29 @@ static Error deepWriteArchive(StringRef
   return Error::success();
 }
 
-static void executeElfObjcopyOnArchive(const CopyConfig &Config,
-                                       const Archive &Ar) {
+/// The function executeObjcopyOnRawBinary does the dispatch based on the format
+/// of the output specified by the command line options.
+static void executeObjcopyOnRawBinary(const CopyConfig &Config,
+                                      MemoryBuffer &In, Buffer &Out) {
+  // TODO: llvm-objcopy should parse CopyConfig.OutputFormat to recognize
+  // formats other than ELF / "binary" and invoke
+  // elf::executeObjcopyOnRawBinary, macho::executeObjcopyOnRawBinary or
+  // coff::executeObjcopyOnRawBinary accordingly.
+  return elf::executeObjcopyOnRawBinary(Config, In, Out);
+}
+
+/// The function executeObjcopyOnBinary does the dispatch based on the format
+/// of the input binary (ELF, MachO or COFF).
+static void executeObjcopyOnBinary(const CopyConfig &Config, object::Binary &In,
+                                   Buffer &Out) {
+  if (auto *ELFBinary = dyn_cast<object::ELFObjectFileBase>(&In))
+    return elf::executeObjcopyOnBinary(Config, *ELFBinary, Out);
+  else
+    error("Unsupported object file format");
+}
+
+static void executeObjcopyOnArchive(const CopyConfig &Config,
+                                    const Archive &Ar) {
   std::vector<NewArchiveMember> NewArchiveMembers;
   Error Err = Error::success();
   for (const Archive::Child &Child : Ar.children(Err)) {
@@ -569,8 +614,7 @@ static void executeElfObjcopyOnArchive(c
       reportError(Ar.getFileName(), ChildNameOrErr.takeError());
 
     MemBuffer MB(ChildNameOrErr.get());
-    ELFReader Reader(Bin);
-    executeElfObjcopyOnBinary(Config, Reader, MB, getOutputElfType(*Bin));
+    executeObjcopyOnBinary(Config, *Bin, MB);
 
     Expected<NewArchiveMember> Member =
         NewArchiveMember::getOldMember(Child, true);
@@ -605,7 +649,10 @@ static void restoreDateOnFile(StringRef
     reportError(Filename, EC);
 }
 
-static void executeElfObjcopy(const CopyConfig &Config) {
+/// The function executeObjcopy does the higher level dispatch based on the type
+/// of input (raw binary, archive or single object file) and takes care of the
+/// format-agnostic modifications, i.e. preserving dates.
+static void executeObjcopy(const CopyConfig &Config) {
   sys::fs::file_status Stat;
   if (Config.PreserveDates)
     if (auto EC = sys::fs::status(Config.InputFilename, Stat))
@@ -615,11 +662,8 @@ static void executeElfObjcopy(const Copy
     auto BufOrErr = MemoryBuffer::getFile(Config.InputFilename);
     if (!BufOrErr)
       reportError(Config.InputFilename, BufOrErr.getError());
-
     FileBuffer FB(Config.OutputFilename);
-    BinaryReader Reader(Config.BinaryArch, BufOrErr->get());
-    executeElfObjcopyOnBinary(Config, Reader, FB,
-                              getOutputElfType(Config.BinaryArch));
+    executeObjcopyOnRawBinary(Config, *BufOrErr->get(), FB);
   } else {
     Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
         createBinary(Config.InputFilename);
@@ -627,12 +671,10 @@ static void executeElfObjcopy(const Copy
       reportError(Config.InputFilename, BinaryOrErr.takeError());
 
     if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary())) {
-      executeElfObjcopyOnArchive(Config, *Ar);
+      executeObjcopyOnArchive(Config, *Ar);
     } else {
       FileBuffer FB(Config.OutputFilename);
-      Binary *Bin = BinaryOrErr.get().getBinary();
-      ELFReader Reader(Bin);
-      executeElfObjcopyOnBinary(Config, Reader, FB, getOutputElfType(*Bin));
+      executeObjcopyOnBinary(Config, *BinaryOrErr.get().getBinary(), FB);
     }
   }
 
@@ -652,5 +694,5 @@ int main(int argc, char **argv) {
   else
     DriverConfig = parseObjcopyOptions(makeArrayRef(argv + 1, argc));
   for (const CopyConfig &CopyConfig : DriverConfig.CopyConfigs)
-    executeElfObjcopy(CopyConfig);
+    executeObjcopy(CopyConfig);
 }




More information about the llvm-commits mailing list