diff --git a/llvm/tools/llvm-objcopy/COFF/COFFConfig.h b/llvm/include/llvm/Object/ObjCopy/COFF/COFFConfig.h
rename from llvm/tools/llvm-objcopy/COFF/COFFConfig.h
rename to llvm/include/llvm/Object/ObjCopy/COFF/COFFConfig.h
--- a/llvm/tools/llvm-objcopy/COFF/COFFConfig.h
+++ b/llvm/include/llvm/Object/ObjCopy/COFF/COFFConfig.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
+#ifndef LLVM_OBJECT_OBJCOPY_COFF_COFFCONFIG_H
+#define LLVM_OBJECT_OBJCOPY_COFF_COFFCONFIG_H
 
 namespace llvm {
 namespace objcopy {
@@ -18,4 +18,4 @@
 } // namespace objcopy
 } // namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
+#endif // LLVM_OBJECT_OBJCOPY_COFF_COFFCONFIG_H
diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h b/llvm/include/llvm/Object/ObjCopy/COFF/COFFObjcopy.h
rename from llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h
rename to llvm/include/llvm/Object/ObjCopy/COFF/COFFObjcopy.h
--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h
+++ b/llvm/include/llvm/Object/ObjCopy/COFF/COFFObjcopy.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H
-#define LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H
+#ifndef LLVM_OBJECT_OBJCOPY_COFF_COFFOBJCOPY_H
+#define LLVM_OBJECT_OBJCOPY_COFF_COFFOBJCOPY_H
 
 namespace llvm {
 class Error;
@@ -23,6 +23,9 @@
 
 namespace coff {
 
+/// Applies the transformations described by \p Config to
+/// \p In(FileFormat::Unspecified) and writes the result into \p Out.
+/// \returns any Error encountered whilst performing the operation.
 Error executeObjcopyOnBinary(const CommonConfig &Config, const COFFConfig &,
                              object::COFFObjectFile &In, raw_ostream &Out);
 
@@ -30,4 +33,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H
+#endif // LLVM_OBJECT_OBJCOPY_COFF_COFFOBJCOPY_H
diff --git a/llvm/tools/llvm-objcopy/CommonConfig.h b/llvm/include/llvm/Object/ObjCopy/CommonConfig.h
rename from llvm/tools/llvm-objcopy/CommonConfig.h
rename to llvm/include/llvm/Object/ObjCopy/CommonConfig.h
--- a/llvm/tools/llvm-objcopy/CommonConfig.h
+++ b/llvm/include/llvm/Object/ObjCopy/CommonConfig.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
+#ifndef LLVM_OBJECT_OBJCOPY_COMMONCONFIG_H
+#define LLVM_OBJECT_OBJCOPY_COMMONCONFIG_H
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/CachedHashString.h"
@@ -256,4 +256,4 @@
 } // namespace objcopy
 } // namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
+#endif // LLVM_OBJECT_OBJCOPY_COMMONCONFIG_H
diff --git a/llvm/include/llvm/Object/ObjCopy/ConfigManager.h b/llvm/include/llvm/Object/ObjCopy/ConfigManager.h
new file mode 100644
--- /dev/null
+++ b/llvm/include/llvm/Object/ObjCopy/ConfigManager.h
@@ -0,0 +1,106 @@
+//===- ConfigManager.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_OBJCOPY_CONFIGMANAGER_H
+#define LLVM_OBJECT_OBJCOPY_CONFIGMANAGER_H
+
+#include "llvm/Object/ObjCopy/COFF/COFFConfig.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
+#include "llvm/Object/ObjCopy/ELF/ELFConfig.h"
+#include "llvm/Object/ObjCopy/MachO/MachOConfig.h"
+#include "llvm/Object/ObjCopy/MultiFormatConfig.h"
+#include "llvm/Object/ObjCopy/wasm/WasmConfig.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace objcopy {
+
+// ConfigManager keeps all configurations and prepare
+// format-specific options.
+struct ConfigManager : public MultiFormatConfig {
+  virtual ~ConfigManager() {}
+
+  const CommonConfig &getCommonConfig() const override { return Common; }
+
+  Expected<const ELFConfig &> getELFConfig() const override { return ELF; }
+
+  Expected<const COFFConfig &> getCOFFConfig() const override {
+    if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
+        !Common.AllocSectionsPrefix.empty() || !Common.DumpSection.empty() ||
+        !Common.KeepSection.empty() || !Common.SymbolsToGlobalize.empty() ||
+        !Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() ||
+        !Common.SymbolsToWeaken.empty() ||
+        !Common.SymbolsToKeepGlobal.empty() ||
+        !Common.SectionsToRename.empty() ||
+        !Common.SetSectionAlignment.empty() || Common.ExtractDWO ||
+        Common.PreserveDates || Common.StripDWO || Common.StripNonAlloc ||
+        Common.StripSections || Common.Weaken ||
+        Common.DecompressDebugSections ||
+        Common.DiscardMode == DiscardType::Locals ||
+        !Common.SymbolsToAdd.empty())
+      return createStringError(llvm::errc::invalid_argument,
+                               "option is not supported for COFF");
+
+    return COFF;
+  }
+
+  Expected<const MachOConfig &> getMachOConfig() const override {
+    if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
+        !Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
+        !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
+        !Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
+        !Common.SymbolsToKeepGlobal.empty() ||
+        !Common.SectionsToRename.empty() ||
+        !Common.UnneededSymbolsToRemove.empty() ||
+        !Common.SetSectionAlignment.empty() ||
+        !Common.SetSectionFlags.empty() || Common.ExtractDWO ||
+        Common.PreserveDates || Common.StripAllGNU || Common.StripDWO ||
+        Common.StripNonAlloc || Common.StripSections || Common.Weaken ||
+        Common.DecompressDebugSections || Common.StripUnneeded ||
+        Common.DiscardMode == DiscardType::Locals ||
+        !Common.SymbolsToAdd.empty())
+      return createStringError(llvm::errc::invalid_argument,
+                               "option is not supported for MachO");
+
+    return MachO;
+  }
+
+  Expected<const WasmConfig &> getWasmConfig() const override {
+    if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
+        !Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
+        !Common.AllocSectionsPrefix.empty() ||
+        Common.DiscardMode != DiscardType::None ||
+        !Common.SymbolsToAdd.empty() || !Common.SymbolsToGlobalize.empty() ||
+        !Common.SymbolsToLocalize.empty() || !Common.SymbolsToKeep.empty() ||
+        !Common.SymbolsToRemove.empty() ||
+        !Common.UnneededSymbolsToRemove.empty() ||
+        !Common.SymbolsToWeaken.empty() ||
+        !Common.SymbolsToKeepGlobal.empty() ||
+        !Common.SectionsToRename.empty() ||
+        !Common.SetSectionAlignment.empty() ||
+        !Common.SetSectionFlags.empty() || !Common.SymbolsToRename.empty())
+      return createStringError(llvm::errc::invalid_argument,
+                               "only flags for section dumping, removal, and "
+                               "addition are supported");
+
+    return Wasm;
+  }
+
+  // All configs.
+  CommonConfig Common;
+  ELFConfig ELF;
+  COFFConfig COFF;
+  MachOConfig MachO;
+  WasmConfig Wasm;
+};
+
+} // namespace objcopy
+} // namespace llvm
+
+#endif // LLVM_OBJECT_OBJCOPY_CONFIGMANAGER_H
diff --git a/llvm/tools/llvm-objcopy/ELF/ELFConfig.h b/llvm/include/llvm/Object/ObjCopy/ELF/ELFConfig.h
rename from llvm/tools/llvm-objcopy/ELF/ELFConfig.h
rename to llvm/include/llvm/Object/ObjCopy/ELF/ELFConfig.h
--- a/llvm/tools/llvm-objcopy/ELF/ELFConfig.h
+++ b/llvm/include/llvm/Object/ObjCopy/ELF/ELFConfig.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
+#ifndef LLVM_OBJECT_OBJCOPY_ELF_ELFCONFIG_H
+#define LLVM_OBJECT_OBJCOPY_ELF_ELFCONFIG_H
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
@@ -35,4 +35,4 @@
 } // namespace objcopy
 } // namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
+#endif // LLVM_OBJECT_OBJCOPY_ELF_ELFCONFIG_H
diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h b/llvm/include/llvm/Object/ObjCopy/ELF/ELFObjcopy.h
rename from llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h
rename to llvm/include/llvm/Object/ObjCopy/ELF/ELFObjcopy.h
--- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h
+++ b/llvm/include/llvm/Object/ObjCopy/ELF/ELFObjcopy.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H
-#define LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H
+#ifndef LLVM_OBJECT_OBJCOPY_ELF_ELFOBJCOPY_H
+#define LLVM_OBJECT_OBJCOPY_ELF_ELFOBJCOPY_H
 
 namespace llvm {
 class Error;
@@ -23,12 +23,24 @@
 struct ELFConfig;
 
 namespace elf {
+/// Applies the transformations described by \p Config and \p ELFConfig to
+/// \p In(FileFormat::IHex) and writes the result into \p Out.
+/// \returns any Error encountered whilst performing the operation.
 Error executeObjcopyOnIHex(const CommonConfig &Config,
                            const ELFConfig &ELFConfig, MemoryBuffer &In,
                            raw_ostream &Out);
+
+/// Applies the transformations described by \p Config and \p ELFConfig to
+/// \p In(FileFormat::Binary) and writes the result into \p Out.
+/// \returns any Error encountered whilst performing the operation.
 Error executeObjcopyOnRawBinary(const CommonConfig &Config,
                                 const ELFConfig &ELFConfig, MemoryBuffer &In,
                                 raw_ostream &Out);
+
+/// Applies the transformations described by \p Config and \p ELFConfig to
+/// \p In(FileFormat::ELF or FileFormat::Unspecified) and writes
+/// the result into \p Out.
+/// \returns any Error encountered whilst performing the operation.
 Error executeObjcopyOnBinary(const CommonConfig &Config,
                              const ELFConfig &ELFConfig,
                              object::ELFObjectFileBase &In, raw_ostream &Out);
@@ -37,4 +49,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H
+#endif // LLVM_OBJECT_OBJCOPY_ELF_ELFOBJCOPY_H
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOConfig.h b/llvm/include/llvm/Object/ObjCopy/MachO/MachOConfig.h
rename from llvm/tools/llvm-objcopy/MachO/MachOConfig.h
rename to llvm/include/llvm/Object/ObjCopy/MachO/MachOConfig.h
--- a/llvm/tools/llvm-objcopy/MachO/MachOConfig.h
+++ b/llvm/include/llvm/Object/ObjCopy/MachO/MachOConfig.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
+#ifndef LLVM_OBJECT_OBJCOPY_MACHO_MACHOCONFIG_H
+#define LLVM_OBJECT_OBJCOPY_MACHO_MACHOCONFIG_H
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
@@ -40,4 +40,4 @@
 } // namespace objcopy
 } // namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
+#endif // LLVM_OBJECT_OBJCOPY_MACHO_MACHOCONFIG_H
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h b/llvm/include/llvm/Object/ObjCopy/MachO/MachOObjcopy.h
rename from llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h
rename to llvm/include/llvm/Object/ObjCopy/MachO/MachOObjcopy.h
--- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h
+++ b/llvm/include/llvm/Object/ObjCopy/MachO/MachOObjcopy.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H
-#define LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H
+#ifndef LLVM_OBJECT_OBJCOPY_MACHO_MACHOOBJCOPY_H
+#define LLVM_OBJECT_OBJCOPY_MACHO_MACHOOBJCOPY_H
 
 namespace llvm {
 class Error;
@@ -24,10 +24,16 @@
 class MultiFormatConfig;
 
 namespace macho {
+/// Applies the transformations described by \p Config and \p MachOConfig to
+/// \p In(FileFormat::Unspecified) and writes the result into \p Out.
+/// \returns any Error encountered whilst performing the operation.
 Error executeObjcopyOnBinary(const CommonConfig &Config,
                              const MachOConfig &MachOConfig,
                              object::MachOObjectFile &In, raw_ostream &Out);
 
+/// Applies the transformations described by \p Config and \p MachOConfig to
+/// \p In(FileFormat::Unspecified) and writes the result into \p Out.
+/// \returns any Error encountered whilst performing the operation.
 Error executeObjcopyOnMachOUniversalBinary(
     const MultiFormatConfig &Config, const object::MachOUniversalBinary &In,
     raw_ostream &Out);
@@ -36,4 +42,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H
+#endif // LLVM_OBJECT_OBJCOPY_MACHO_MACHOOBJCOPY_H
diff --git a/llvm/tools/llvm-objcopy/MultiFormatConfig.h b/llvm/include/llvm/Object/ObjCopy/MultiFormatConfig.h
rename from llvm/tools/llvm-objcopy/MultiFormatConfig.h
rename to llvm/include/llvm/Object/ObjCopy/MultiFormatConfig.h
--- a/llvm/tools/llvm-objcopy/MultiFormatConfig.h
+++ b/llvm/include/llvm/Object/ObjCopy/MultiFormatConfig.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
+#ifndef LLVM_OBJECT_OBJCOPY_MULTIFORMATCONFIG_H
+#define LLVM_OBJECT_OBJCOPY_MULTIFORMATCONFIG_H
 
 #include "llvm/Support/Error.h"
 
@@ -34,4 +34,4 @@
 } // namespace objcopy
 } // namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
+#endif // LLVM_OBJECT_OBJCOPY_MULTIFORMATCONFIG_H
diff --git a/llvm/include/llvm/Object/ObjCopy/ObjCopy.h b/llvm/include/llvm/Object/ObjCopy/ObjCopy.h
new file mode 100644
--- /dev/null
+++ b/llvm/include/llvm/Object/ObjCopy/ObjCopy.h
@@ -0,0 +1,47 @@
+//===- ObjCopy.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_OBJCOPY_OBJCOPY_H
+#define LLVM_OBJECT_OBJCOPY_OBJCOPY_H
+
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ArchiveWriter.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
+#include "llvm/Object/ObjCopy/MultiFormatConfig.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace objcopy {
+
+/// Applies the transformations described by \p Config to
+/// each member in archive \p Ar.
+/// \returns Vector of transformed archive members.
+Expected<std::vector<NewArchiveMember>>
+createNewArchiveMembers(const MultiFormatConfig &Config,
+                        const object::Archive &Ar);
+
+/// Applies the transformations described by \p Config to
+/// each member in archive \p Ar.
+/// Writes a result in a file specified by \p Config.OutputFilename.
+/// \returns any Error encountered whilst performing the operation.
+Error executeObjcopyOnArchive(const MultiFormatConfig &Config,
+                              const object::Archive &Ar);
+
+/// Applies the transformations described by \p Config to \p In and writes
+/// the result into \p Out. This function does the dispatch based on the
+/// format of the input binary (COFF, ELF, MachO or wasm).
+/// \returns any Error encountered whilst performing the operation.
+Error executeObjcopyOnBinary(const MultiFormatConfig &Config,
+                             object::Binary &In, raw_ostream &Out);
+
+} // end namespace objcopy
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_OBJCOPY_OBJCOPY_H
diff --git a/llvm/tools/llvm-objcopy/wasm/WasmConfig.h b/llvm/include/llvm/Object/ObjCopy/wasm/WasmConfig.h
rename from llvm/tools/llvm-objcopy/wasm/WasmConfig.h
rename to llvm/include/llvm/Object/ObjCopy/wasm/WasmConfig.h
--- a/llvm/tools/llvm-objcopy/wasm/WasmConfig.h
+++ b/llvm/include/llvm/Object/ObjCopy/wasm/WasmConfig.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
+#ifndef LLVM_OBJECT_OBJCOPY_WASM_WASMCONFIG_H
+#define LLVM_OBJECT_OBJCOPY_WASM_WASMCONFIG_H
 
 namespace llvm {
 namespace objcopy {
@@ -18,4 +18,4 @@
 } // namespace objcopy
 } // namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
+#endif // LLVM_OBJECT_OBJCOPY_WASM_WASMCONFIG_H
diff --git a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h b/llvm/include/llvm/Object/ObjCopy/wasm/WasmObjcopy.h
rename from llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h
rename to llvm/include/llvm/Object/ObjCopy/wasm/WasmObjcopy.h
--- a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h
+++ b/llvm/include/llvm/Object/ObjCopy/wasm/WasmObjcopy.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMOBJCOPY_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMOBJCOPY_H
+#ifndef LLVM_OBJECT_OBJCOPY_WASM_WASMOBJCOPY_H
+#define LLVM_OBJECT_OBJCOPY_WASM_WASMOBJCOPY_H
 
 namespace llvm {
 class Error;
@@ -22,6 +22,9 @@
 struct WasmConfig;
 
 namespace wasm {
+/// Applies the transformations described by \p Config to
+/// \p In(FileFormat::Unspecified) and writes the result into \p Out.
+/// \returns any Error encountered whilst performing the operation.
 Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &,
                              object::WasmObjectFile &In, raw_ostream &Out);
 
@@ -29,4 +32,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMOBJCOPY_H
+#endif // LLVM_OBJECT_OBJCOPY_WASM_WASMOBJCOPY_H
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -29,6 +29,22 @@
   WindowsMachineFlag.cpp
   WindowsResource.cpp
   XCOFFObjectFile.cpp
+  ObjCopy/ObjCopy.cpp
+  ObjCopy/COFF/COFFObjcopy.cpp
+  ObjCopy/COFF/Object.cpp
+  ObjCopy/COFF/Reader.cpp
+  ObjCopy/COFF/Writer.cpp
+  ObjCopy/ELF/ELFObjcopy.cpp
+  ObjCopy/ELF/Object.cpp
+  ObjCopy/MachO/MachOObjcopy.cpp
+  ObjCopy/MachO/MachOReader.cpp
+  ObjCopy/MachO/MachOWriter.cpp
+  ObjCopy/MachO/MachOLayoutBuilder.cpp
+  ObjCopy/MachO/Object.cpp
+  ObjCopy/wasm/Object.cpp
+  ObjCopy/wasm/Reader.cpp
+  ObjCopy/wasm/Writer.cpp
+  ObjCopy/wasm/WasmObjcopy.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Object
diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/lib/Object/ObjCopy/COFF/COFFObjcopy.cpp
rename from llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
rename to llvm/lib/Object/ObjCopy/COFF/COFFObjcopy.cpp
--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+++ b/llvm/lib/Object/ObjCopy/COFF/COFFObjcopy.cpp
@@ -6,12 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "COFFObjcopy.h"
-#include "COFFConfig.h"
-#include "CommonConfig.h"
+#include "llvm/Object/ObjCopy/COFF/COFFObjcopy.h"
 #include "Object.h"
 #include "Reader.h"
 #include "Writer.h"
+#include "llvm/Object/ObjCopy/COFF/COFFConfig.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
 
 #include "llvm/Object/Binary.h"
 #include "llvm/Object/COFF.h"
diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/lib/Object/ObjCopy/COFF/Object.h
rename from llvm/tools/llvm-objcopy/COFF/Object.h
rename to llvm/lib/Object/ObjCopy/COFF/Object.h
--- a/llvm/tools/llvm-objcopy/COFF/Object.h
+++ b/llvm/lib/Object/ObjCopy/COFF/Object.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H
-#define LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_COFF_OBJECT_H
+#define LLVM_LIB_OBJECT_OBJCOPY_COFF_OBJECT_H
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
@@ -208,4 +208,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_COFF_OBJECT_H
diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/lib/Object/ObjCopy/COFF/Object.cpp
rename from llvm/tools/llvm-objcopy/COFF/Object.cpp
rename to llvm/lib/Object/ObjCopy/COFF/Object.cpp
diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.h b/llvm/lib/Object/ObjCopy/COFF/Reader.h
rename from llvm/tools/llvm-objcopy/COFF/Reader.h
rename to llvm/lib/Object/ObjCopy/COFF/Reader.h
--- a/llvm/tools/llvm-objcopy/COFF/Reader.h
+++ b/llvm/lib/Object/ObjCopy/COFF/Reader.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_OBJCOPY_COFF_READER_H
-#define LLVM_TOOLS_OBJCOPY_COFF_READER_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_COFF_READER_H
+#define LLVM_LIB_OBJECT_OBJCOPY_COFF_READER_H
 
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/Object/COFF.h"
@@ -38,4 +38,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_OBJCOPY_COFF_READER_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_COFF_READER_H
diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/lib/Object/ObjCopy/COFF/Reader.cpp
rename from llvm/tools/llvm-objcopy/COFF/Reader.cpp
rename to llvm/lib/Object/ObjCopy/COFF/Reader.cpp
diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/lib/Object/ObjCopy/COFF/Writer.h
rename from llvm/tools/llvm-objcopy/COFF/Writer.h
rename to llvm/lib/Object/ObjCopy/COFF/Writer.h
--- a/llvm/tools/llvm-objcopy/COFF/Writer.h
+++ b/llvm/lib/Object/ObjCopy/COFF/Writer.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_OBJCOPY_COFF_WRITER_H
-#define LLVM_TOOLS_OBJCOPY_COFF_WRITER_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_COFF_WRITER_H
+#define LLVM_LIB_OBJECT_OBJCOPY_COFF_WRITER_H
 
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Support/Error.h"
@@ -60,4 +60,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_OBJCOPY_COFF_WRITER_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_COFF_WRITER_H
diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/lib/Object/ObjCopy/COFF/Writer.cpp
rename from llvm/tools/llvm-objcopy/COFF/Writer.cpp
rename to llvm/lib/Object/ObjCopy/COFF/Writer.cpp
diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/lib/Object/ObjCopy/ELF/ELFObjcopy.cpp
rename from llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
rename to llvm/lib/Object/ObjCopy/ELF/ELFObjcopy.cpp
--- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/Object/ObjCopy/ELF/ELFObjcopy.cpp
@@ -6,11 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ELFObjcopy.h"
-#include "CommonConfig.h"
-#include "ELFConfig.h"
+#include "llvm/Object/ObjCopy/ELF/ELFObjcopy.h"
 #include "Object.h"
-#include "llvm-objcopy.h"
 #include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Optional.h"
@@ -24,6 +21,8 @@
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/ELFTypes.h"
 #include "llvm/Object/Error.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
+#include "llvm/Object/ObjCopy/ELF/ELFConfig.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compression.h"
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/lib/Object/ObjCopy/ELF/Object.h
rename from llvm/tools/llvm-objcopy/ELF/Object.h
rename to llvm/lib/Object/ObjCopy/ELF/Object.h
--- a/llvm/tools/llvm-objcopy/ELF/Object.h
+++ b/llvm/lib/Object/ObjCopy/ELF/Object.h
@@ -6,16 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_OBJCOPY_OBJECT_H
-#define LLVM_TOOLS_OBJCOPY_OBJECT_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_ELF_OBJECT_H
+#define LLVM_LIB_OBJECT_OBJCOPY_ELF_OBJECT_H
 
-#include "CommonConfig.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -1093,4 +1093,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_OBJCOPY_OBJECT_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_ELF_OBJECT_H
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/lib/Object/ObjCopy/ELF/Object.cpp
rename from llvm/tools/llvm-objcopy/ELF/Object.cpp
rename to llvm/lib/Object/ObjCopy/ELF/Object.cpp
--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/llvm/lib/Object/ObjCopy/ELF/Object.cpp
@@ -1792,9 +1792,9 @@
     Sec->EntrySize = Shdr.sh_entsize;
     Sec->Index = Index++;
     Sec->OriginalIndex = Sec->Index;
-    Sec->OriginalData =
-        ArrayRef<uint8_t>(ElfFile.base() + Shdr.sh_offset,
-                          (Shdr.sh_type == SHT_NOBITS) ? (size_t)0 : Shdr.sh_size);
+    Sec->OriginalData = ArrayRef<uint8_t>(
+        ElfFile.base() + Shdr.sh_offset,
+        (Shdr.sh_type == SHT_NOBITS) ? (size_t)0 : Shdr.sh_size);
   }
 
   return Error::success();
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h b/llvm/lib/Object/ObjCopy/MachO/MachOLayoutBuilder.h
rename from llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h
rename to llvm/lib/Object/ObjCopy/MachO/MachOLayoutBuilder.h
--- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h
+++ b/llvm/lib/Object/ObjCopy/MachO/MachOLayoutBuilder.h
@@ -6,11 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H
-#define LLVM_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H
+#define LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H
 
-#include "MachOObjcopy.h"
 #include "Object.h"
+#include "llvm/Object/ObjCopy/MachO/MachOObjcopy.h"
 
 namespace llvm {
 namespace objcopy {
@@ -51,4 +51,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp b/llvm/lib/Object/ObjCopy/MachO/MachOLayoutBuilder.cpp
rename from llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
rename to llvm/lib/Object/ObjCopy/MachO/MachOLayoutBuilder.cpp
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/lib/Object/ObjCopy/MachO/MachOObjcopy.cpp
rename from llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
rename to llvm/lib/Object/ObjCopy/MachO/MachOObjcopy.cpp
--- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
+++ b/llvm/lib/Object/ObjCopy/MachO/MachOObjcopy.cpp
@@ -6,17 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "MachOObjcopy.h"
-#include "../llvm-objcopy.h"
-#include "CommonConfig.h"
-#include "MachO/MachOConfig.h"
+#include "llvm/Object/ObjCopy/MachO/MachOObjcopy.h"
 #include "MachOReader.h"
 #include "MachOWriter.h"
-#include "MultiFormatConfig.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/Object/ArchiveWriter.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/MachOUniversalWriter.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
+#include "llvm/Object/ObjCopy/MachO/MachOConfig.h"
+#include "llvm/Object/ObjCopy/MultiFormatConfig.h"
+#include "llvm/Object/ObjCopy/ObjCopy.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileOutputBuffer.h"
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.h b/llvm/lib/Object/ObjCopy/MachO/MachOReader.h
rename from llvm/tools/llvm-objcopy/MachO/MachOReader.h
rename to llvm/lib/Object/ObjCopy/MachO/MachOReader.h
--- a/llvm/tools/llvm-objcopy/MachO/MachOReader.h
+++ b/llvm/lib/Object/ObjCopy/MachO/MachOReader.h
@@ -6,10 +6,13 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "MachOObjcopy.h"
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOREADER_H
+#define LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOREADER_H
+
 #include "Object.h"
 #include "llvm/BinaryFormat/MachO.h"
 #include "llvm/Object/MachO.h"
+#include "llvm/Object/ObjCopy/MachO/MachOObjcopy.h"
 #include <memory>
 
 namespace llvm {
@@ -53,3 +56,5 @@
 } // end namespace macho
 } // end namespace objcopy
 } // end namespace llvm
+
+#endif // LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOREADER_H
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/lib/Object/ObjCopy/MachO/MachOReader.cpp
rename from llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
rename to llvm/lib/Object/ObjCopy/MachO/MachOReader.cpp
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.h b/llvm/lib/Object/ObjCopy/MachO/MachOWriter.h
rename from llvm/tools/llvm-objcopy/MachO/MachOWriter.h
rename to llvm/lib/Object/ObjCopy/MachO/MachOWriter.h
--- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.h
+++ b/llvm/lib/Object/ObjCopy/MachO/MachOWriter.h
@@ -6,11 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOWRITER_H
+#define LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOWRITER_H
+
 #include "MachOLayoutBuilder.h"
-#include "MachOObjcopy.h"
 #include "Object.h"
 #include "llvm/BinaryFormat/MachO.h"
 #include "llvm/Object/MachO.h"
+#include "llvm/Object/ObjCopy/MachO/MachOObjcopy.h"
 
 namespace llvm {
 class Error;
@@ -66,3 +69,5 @@
 } // end namespace macho
 } // end namespace objcopy
 } // end namespace llvm
+
+#endif // LLVM_LIB_OBJECT_OBJCOPY_MACHO_MACHOWRITER_H
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp b/llvm/lib/Object/ObjCopy/MachO/MachOWriter.cpp
rename from llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
rename to llvm/lib/Object/ObjCopy/MachO/MachOWriter.cpp
diff --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/lib/Object/ObjCopy/MachO/Object.h
rename from llvm/tools/llvm-objcopy/MachO/Object.h
rename to llvm/lib/Object/ObjCopy/MachO/Object.h
--- a/llvm/tools/llvm-objcopy/MachO/Object.h
+++ b/llvm/lib/Object/ObjCopy/MachO/Object.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_OBJCOPY_MACHO_OBJECT_H
-#define LLVM_OBJCOPY_MACHO_OBJECT_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_MACHO_OBJECT_H
+#define LLVM_LIB_OBJECT_OBJCOPY_MACHO_OBJECT_H
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
@@ -363,4 +363,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_OBJCOPY_MACHO_OBJECT_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_MACHO_OBJECT_H
diff --git a/llvm/tools/llvm-objcopy/MachO/Object.cpp b/llvm/lib/Object/ObjCopy/MachO/Object.cpp
rename from llvm/tools/llvm-objcopy/MachO/Object.cpp
rename to llvm/lib/Object/ObjCopy/MachO/Object.cpp
diff --git a/llvm/lib/Object/ObjCopy/ObjCopy.cpp b/llvm/lib/Object/ObjCopy/ObjCopy.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/lib/Object/ObjCopy/ObjCopy.cpp
@@ -0,0 +1,157 @@
+//===- Objcopy.cpp --------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/ObjCopy/ObjCopy.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/ELFTypes.h"
+#include "llvm/Object/Error.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Object/MachOUniversal.h"
+#include "llvm/Object/ObjCopy/COFF/COFFConfig.h"
+#include "llvm/Object/ObjCopy/COFF/COFFObjcopy.h"
+#include "llvm/Object/ObjCopy/ELF/ELFConfig.h"
+#include "llvm/Object/ObjCopy/ELF/ELFObjcopy.h"
+#include "llvm/Object/ObjCopy/MachO/MachOConfig.h"
+#include "llvm/Object/ObjCopy/MachO/MachOObjcopy.h"
+#include "llvm/Object/ObjCopy/wasm/WasmConfig.h"
+#include "llvm/Object/ObjCopy/wasm/WasmObjcopy.h"
+#include "llvm/Object/Wasm.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
+
+namespace llvm {
+namespace objcopy {
+
+using namespace llvm::object;
+
+Expected<std::vector<NewArchiveMember>>
+createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {
+  std::vector<NewArchiveMember> NewArchiveMembers;
+  Error Err = Error::success();
+  for (const Archive::Child &Child : Ar.children(Err)) {
+    Expected<StringRef> ChildNameOrErr = Child.getName();
+    if (!ChildNameOrErr)
+      return createFileError(Ar.getFileName(), ChildNameOrErr.takeError());
+
+    Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
+    if (!ChildOrErr)
+      return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",
+                             ChildOrErr.takeError());
+
+    SmallVector<char, 0> Buffer;
+    raw_svector_ostream MemStream(Buffer);
+
+    if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
+      return std::move(E);
+
+    Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
+        Child, Config.getCommonConfig().DeterministicArchives);
+    if (!Member)
+      return createFileError(Ar.getFileName(), Member.takeError());
+
+    Member->Buf = std::make_unique<SmallVectorMemoryBuffer>(
+        std::move(Buffer), ChildNameOrErr.get());
+    Member->MemberName = Member->Buf->getBufferIdentifier();
+    NewArchiveMembers.push_back(std::move(*Member));
+  }
+  if (Err)
+    return createFileError(Config.getCommonConfig().InputFilename,
+                           std::move(Err));
+  return std::move(NewArchiveMembers);
+}
+
+// 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,
+                              ArrayRef<NewArchiveMember> NewMembers,
+                              bool WriteSymtab, object::Archive::Kind Kind,
+                              bool Deterministic, bool Thin) {
+  if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind,
+                             Deterministic, Thin))
+    return createFileError(ArcName, std::move(E));
+
+  if (!Thin)
+    return Error::success();
+
+  for (const NewArchiveMember &Member : NewMembers) {
+    // For regular files (as is the case for deepWriteArchive),
+    // FileOutputBuffer::create will return OnDiskBuffer.
+    // OnDiskBuffer uses a temporary file and then renames it. So in reality
+    // there is no inefficiency / duplicated in-memory buffers in this case. For
+    // now in-memory buffers can not be completely avoided since
+    // NewArchiveMember still requires them even though writeArchive does not
+    // write them on disk.
+    Expected<std::unique_ptr<FileOutputBuffer>> FB =
+        FileOutputBuffer::create(Member.MemberName, Member.Buf->getBufferSize(),
+                                 FileOutputBuffer::F_executable);
+    if (!FB)
+      return FB.takeError();
+    std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
+              (*FB)->getBufferStart());
+    if (Error E = (*FB)->commit())
+      return E;
+  }
+  return Error::success();
+}
+
+Error executeObjcopyOnArchive(const MultiFormatConfig &Config,
+                              const object::Archive &Ar) {
+  Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
+      createNewArchiveMembers(Config, Ar);
+  if (!NewArchiveMembersOrErr)
+    return NewArchiveMembersOrErr.takeError();
+  const CommonConfig &CommonConfig = Config.getCommonConfig();
+  return deepWriteArchive(CommonConfig.OutputFilename, *NewArchiveMembersOrErr,
+                          Ar.hasSymbolTable(), Ar.kind(),
+                          CommonConfig.DeterministicArchives, Ar.isThin());
+}
+
+/// The function executeObjcopyOnBinary does the dispatch based on the format
+/// of the input binary (ELF, MachO or COFF).
+Error executeObjcopyOnBinary(const MultiFormatConfig &Config,
+                             object::Binary &In, raw_ostream &Out) {
+  if (auto *ELFBinary = dyn_cast<object::ELFObjectFileBase>(&In)) {
+    Expected<const ELFConfig &> ELFConfig = Config.getELFConfig();
+    if (!ELFConfig)
+      return ELFConfig.takeError();
+
+    return elf::executeObjcopyOnBinary(Config.getCommonConfig(), *ELFConfig,
+                                       *ELFBinary, Out);
+  } else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In)) {
+    Expected<const COFFConfig &> COFFConfig = Config.getCOFFConfig();
+    if (!COFFConfig)
+      return COFFConfig.takeError();
+
+    return coff::executeObjcopyOnBinary(Config.getCommonConfig(), *COFFConfig,
+                                        *COFFBinary, Out);
+  } else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In)) {
+    Expected<const MachOConfig &> MachOConfig = Config.getMachOConfig();
+    if (!MachOConfig)
+      return MachOConfig.takeError();
+
+    return macho::executeObjcopyOnBinary(Config.getCommonConfig(), *MachOConfig,
+                                         *MachOBinary, Out);
+  } else if (auto *MachOUniversalBinary =
+                 dyn_cast<object::MachOUniversalBinary>(&In)) {
+    return macho::executeObjcopyOnMachOUniversalBinary(
+        Config, *MachOUniversalBinary, Out);
+  } else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In)) {
+    Expected<const WasmConfig &> WasmConfig = Config.getWasmConfig();
+    if (!WasmConfig)
+      return WasmConfig.takeError();
+
+    return objcopy::wasm::executeObjcopyOnBinary(Config.getCommonConfig(),
+                                                 *WasmConfig, *WasmBinary, Out);
+  } else
+    return createStringError(object_error::invalid_file_type,
+                             "unsupported object file format");
+}
+
+} // end namespace objcopy
+} // end namespace llvm
diff --git a/llvm/tools/llvm-objcopy/wasm/Object.h b/llvm/lib/Object/ObjCopy/wasm/Object.h
rename from llvm/tools/llvm-objcopy/wasm/Object.h
rename to llvm/lib/Object/ObjCopy/wasm/Object.h
--- a/llvm/tools/llvm-objcopy/wasm/Object.h
+++ b/llvm/lib/Object/ObjCopy/wasm/Object.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_OBJECT_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_WASM_OBJECT_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_WASM_OBJECT_H
+#define LLVM_LIB_OBJECT_OBJCOPY_WASM_OBJECT_H
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
@@ -44,4 +44,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_OBJECT_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_WASM_OBJECT_H
diff --git a/llvm/tools/llvm-objcopy/wasm/Object.cpp b/llvm/lib/Object/ObjCopy/wasm/Object.cpp
rename from llvm/tools/llvm-objcopy/wasm/Object.cpp
rename to llvm/lib/Object/ObjCopy/wasm/Object.cpp
diff --git a/llvm/tools/llvm-objcopy/wasm/Reader.h b/llvm/lib/Object/ObjCopy/wasm/Reader.h
rename from llvm/tools/llvm-objcopy/wasm/Reader.h
rename to llvm/lib/Object/ObjCopy/wasm/Reader.h
--- a/llvm/tools/llvm-objcopy/wasm/Reader.h
+++ b/llvm/lib/Object/ObjCopy/wasm/Reader.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_READER_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_WASM_READER_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_WASM_READER_H
+#define LLVM_LIB_OBJECT_OBJCOPY_WASM_READER_H
 
 #include "Object.h"
 
@@ -28,4 +28,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_READER_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_WASM_READER_H
diff --git a/llvm/tools/llvm-objcopy/wasm/Reader.cpp b/llvm/lib/Object/ObjCopy/wasm/Reader.cpp
rename from llvm/tools/llvm-objcopy/wasm/Reader.cpp
rename to llvm/lib/Object/ObjCopy/wasm/Reader.cpp
diff --git a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp b/llvm/lib/Object/ObjCopy/wasm/WasmObjcopy.cpp
rename from llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
rename to llvm/lib/Object/ObjCopy/wasm/WasmObjcopy.cpp
--- a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
+++ b/llvm/lib/Object/ObjCopy/wasm/WasmObjcopy.cpp
@@ -6,11 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "WasmObjcopy.h"
-#include "CommonConfig.h"
+#include "llvm/Object/ObjCopy/wasm/WasmObjcopy.h"
 #include "Object.h"
 #include "Reader.h"
 #include "Writer.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/FileOutputBuffer.h"
 
diff --git a/llvm/tools/llvm-objcopy/wasm/Writer.h b/llvm/lib/Object/ObjCopy/wasm/Writer.h
rename from llvm/tools/llvm-objcopy/wasm/Writer.h
rename to llvm/lib/Object/ObjCopy/wasm/Writer.h
--- a/llvm/tools/llvm-objcopy/wasm/Writer.h
+++ b/llvm/lib/Object/ObjCopy/wasm/Writer.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_WRITER_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_WASM_WRITER_H
+#ifndef LLVM_LIB_OBJECT_OBJCOPY_WASM_WRITER_H
+#define LLVM_LIB_OBJECT_OBJCOPY_WASM_WRITER_H
 
 #include "Object.h"
 #include <cstdint>
@@ -46,4 +46,4 @@
 } // end namespace objcopy
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_WRITER_H
+#endif // LLVM_LIB_OBJECT_OBJCOPY_WASM_WRITER_H
diff --git a/llvm/tools/llvm-objcopy/wasm/Writer.cpp b/llvm/lib/Object/ObjCopy/wasm/Writer.cpp
rename from llvm/tools/llvm-objcopy/wasm/Writer.cpp
rename to llvm/lib/Object/ObjCopy/wasm/Writer.cpp
diff --git a/llvm/tools/llvm-objcopy/CMakeLists.txt b/llvm/tools/llvm-objcopy/CMakeLists.txt
--- a/llvm/tools/llvm-objcopy/CMakeLists.txt
+++ b/llvm/tools/llvm-objcopy/CMakeLists.txt
@@ -22,23 +22,8 @@
 add_public_tablegen_target(StripOptsTableGen)
 
 add_llvm_tool(llvm-objcopy
-  ConfigManager.cpp
+  ObjcopyOptions.cpp
   llvm-objcopy.cpp
-  COFF/COFFObjcopy.cpp
-  COFF/Object.cpp
-  COFF/Reader.cpp
-  COFF/Writer.cpp
-  ELF/ELFObjcopy.cpp
-  ELF/Object.cpp
-  MachO/MachOObjcopy.cpp
-  MachO/MachOReader.cpp
-  MachO/MachOWriter.cpp
-  MachO/MachOLayoutBuilder.cpp
-  MachO/Object.cpp
-  wasm/Object.cpp
-  wasm/Reader.cpp
-  wasm/Writer.cpp
-  wasm/WasmObjcopy.cpp
   DEPENDS
   ObjcopyOptsTableGen
   InstallNameToolOptsTableGen
diff --git a/llvm/tools/llvm-objcopy/ConfigManager.h b/llvm/tools/llvm-objcopy/ObjcopyOptions.h
rename from llvm/tools/llvm-objcopy/ConfigManager.h
rename to llvm/tools/llvm-objcopy/ObjcopyOptions.h
--- a/llvm/tools/llvm-objcopy/ConfigManager.h
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.h
@@ -1,4 +1,4 @@
-//===- ConfigManager.h ----------------------------------------------------===//
+//===- ObjcopyOptions.h ---------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,40 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
+#ifndef LLVM_TOOLS_LLVM_OBJCOPY_OBJCOPYOPTIONS_H
+#define LLVM_TOOLS_LLVM_OBJCOPY_OBJCOPYOPTIONS_H
 
-#include "COFF/COFFConfig.h"
-#include "CommonConfig.h"
-#include "ELF/ELFConfig.h"
-#include "MachO/MachOConfig.h"
-#include "MultiFormatConfig.h"
-#include "wasm/WasmConfig.h"
+#include "llvm/Object/ObjCopy/ConfigManager.h"
 #include "llvm/Support/Allocator.h"
 #include <vector>
 
 namespace llvm {
 namespace objcopy {
 
-// ConfigManager keeps all configurations and prepare
-// format-specific options.
-struct ConfigManager : public MultiFormatConfig {
-  virtual ~ConfigManager() {}
-
-  const CommonConfig &getCommonConfig() const override { return Common; }
-  Expected<const ELFConfig &> getELFConfig() const override;
-  Expected<const COFFConfig &> getCOFFConfig() const override;
-  Expected<const MachOConfig &> getMachOConfig() const override;
-  Expected<const WasmConfig &> getWasmConfig() const override;
-
-  // All configs.
-  CommonConfig Common;
-  ELFConfig ELF;
-  COFFConfig COFF;
-  MachOConfig MachO;
-  WasmConfig Wasm;
-};
-
 // Configuration for the overall invocation of this tool. When invoked as
 // objcopy, will always contain exactly one CopyConfig. When invoked as strip,
 // will contain one or more CopyConfigs.
@@ -77,4 +53,4 @@
 } // namespace objcopy
 } // namespace llvm
 
-#endif // LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
+#endif // LLVM_TOOLS_LLVM_OBJCOPY_OBJCOPYOPTIONS_H
diff --git a/llvm/tools/llvm-objcopy/ConfigManager.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
rename from llvm/tools/llvm-objcopy/ConfigManager.cpp
rename to llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
--- a/llvm/tools/llvm-objcopy/ConfigManager.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -1,4 +1,4 @@
-//===- ConfigManager.cpp --------------------------------------------------===//
+//===- ObjcopyOptions.cpp -------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ConfigManager.h"
+#include "ObjcopyOptions.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -558,68 +558,6 @@
   return SI;
 }
 
-Expected<const ELFConfig &> ConfigManager::getELFConfig() const {
-  return ELF;
-}
-
-Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
-  if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
-      !Common.AllocSectionsPrefix.empty() || !Common.DumpSection.empty() ||
-      !Common.KeepSection.empty() || !Common.SymbolsToGlobalize.empty() ||
-      !Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() ||
-      !Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
-      !Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
-      Common.ExtractDWO || Common.PreserveDates || Common.StripDWO ||
-      Common.StripNonAlloc || Common.StripSections || Common.Weaken ||
-      Common.DecompressDebugSections ||
-      Common.DiscardMode == DiscardType::Locals ||
-      !Common.SymbolsToAdd.empty()) {
-    return createStringError(llvm::errc::invalid_argument,
-                             "option not supported by llvm-objcopy for COFF");
-  }
-
-  return COFF;
-}
-
-Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
-  if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
-      !Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
-      !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
-      !Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
-      !Common.SymbolsToKeepGlobal.empty() || !Common.SectionsToRename.empty() ||
-      !Common.UnneededSymbolsToRemove.empty() ||
-      !Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
-      Common.ExtractDWO || Common.PreserveDates || Common.StripAllGNU ||
-      Common.StripDWO || Common.StripNonAlloc || Common.StripSections ||
-      Common.Weaken || Common.DecompressDebugSections || Common.StripUnneeded ||
-      Common.DiscardMode == DiscardType::Locals ||
-      !Common.SymbolsToAdd.empty()) {
-    return createStringError(llvm::errc::invalid_argument,
-                             "option not supported by llvm-objcopy for MachO");
-  }
-
-  return MachO;
-}
-
-Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
-  if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
-      !Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
-      !Common.AllocSectionsPrefix.empty() ||
-      Common.DiscardMode != DiscardType::None || !Common.SymbolsToAdd.empty() ||
-      !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToLocalize.empty() ||
-      !Common.SymbolsToKeep.empty() || !Common.SymbolsToRemove.empty() ||
-      !Common.UnneededSymbolsToRemove.empty() ||
-      !Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
-      !Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
-      !Common.SetSectionFlags.empty() || !Common.SymbolsToRename.empty()) {
-    return createStringError(
-        llvm::errc::invalid_argument,
-        "only flags for section dumping, removal, and addition are supported");
-  }
-
-  return Wasm;
-}
-
 // ParseObjcopyOptions returns the config and sets the input arguments. If a
 // help flag is set then ParseObjcopyOptions will print the help messege and
 // exit.
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.h b/llvm/tools/llvm-objcopy/llvm-objcopy.h
deleted file mode 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- llvm-objcopy.h -------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_OBJCOPY_OBJCOPY_H
-#define LLVM_TOOLS_OBJCOPY_OBJCOPY_H
-
-#include "llvm/Support/Error.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-struct NewArchiveMember;
-
-namespace object {
-
-class Archive;
-
-} // end namespace object
-
-namespace objcopy {
-class MultiFormatConfig;
-Expected<std::vector<NewArchiveMember>>
-createNewArchiveMembers(const MultiFormatConfig &Config,
-                        const object::Archive &Ar);
-
-} // end namespace objcopy
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_OBJCOPY_OBJCOPY_H
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -6,17 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm-objcopy.h"
-#include "COFF/COFFConfig.h"
-#include "COFF/COFFObjcopy.h"
-#include "CommonConfig.h"
-#include "ConfigManager.h"
-#include "ELF/ELFConfig.h"
-#include "ELF/ELFObjcopy.h"
-#include "MachO/MachOConfig.h"
-#include "MachO/MachOObjcopy.h"
-#include "wasm/WasmConfig.h"
-#include "wasm/WasmObjcopy.h"
+#include "ObjcopyOptions.h"
+#include "llvm/Object/ObjCopy/COFF/COFFConfig.h"
+#include "llvm/Object/ObjCopy/COFF/COFFObjcopy.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
+#include "llvm/Object/ObjCopy/ELF/ELFConfig.h"
+#include "llvm/Object/ObjCopy/ELF/ELFObjcopy.h"
+#include "llvm/Object/ObjCopy/MachO/MachOConfig.h"
+#include "llvm/Object/ObjCopy/MachO/MachOObjcopy.h"
+#include "llvm/Object/ObjCopy/ObjCopy.h"
+#include "llvm/Object/ObjCopy/wasm/WasmConfig.h"
+#include "llvm/Object/ObjCopy/wasm/WasmObjcopy.h"
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -96,40 +96,6 @@
     return parseObjcopyOptions(Args, reportWarning);
 }
 
-// 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,
-                              ArrayRef<NewArchiveMember> NewMembers,
-                              bool WriteSymtab, object::Archive::Kind Kind,
-                              bool Deterministic, bool Thin) {
-  if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind,
-                             Deterministic, Thin))
-    return createFileError(ArcName, std::move(E));
-
-  if (!Thin)
-    return Error::success();
-
-  for (const NewArchiveMember &Member : NewMembers) {
-    // For regular files (as is the case for deepWriteArchive),
-    // FileOutputBuffer::create will return OnDiskBuffer.
-    // OnDiskBuffer uses a temporary file and then renames it. So in reality
-    // there is no inefficiency / duplicated in-memory buffers in this case. For
-    // now in-memory buffers can not be completely avoided since
-    // NewArchiveMember still requires them even though writeArchive does not
-    // write them on disk.
-    Expected<std::unique_ptr<FileOutputBuffer>> FB =
-        FileOutputBuffer::create(Member.MemberName, Member.Buf->getBufferSize(),
-                                 FileOutputBuffer::F_executable);
-    if (!FB)
-      return FB.takeError();
-    std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
-              (*FB)->getBufferStart());
-    if (Error E = (*FB)->commit())
-      return E;
-  }
-  return Error::success();
-}
-
 /// The function executeObjcopyOnIHex does the dispatch based on the format
 /// of the output specified by the command line options.
 static Error executeObjcopyOnIHex(ConfigManager &ConfigMgr, MemoryBuffer &In,
@@ -166,101 +132,6 @@
   llvm_unreachable("unsupported output format");
 }
 
-/// The function executeObjcopyOnBinary does the dispatch based on the format
-/// of the input binary (ELF, MachO or COFF).
-static Error executeObjcopyOnBinary(const MultiFormatConfig &Config,
-                                    object::Binary &In, raw_ostream &Out) {
-  if (auto *ELFBinary = dyn_cast<object::ELFObjectFileBase>(&In)) {
-    Expected<const ELFConfig &> ELFConfig = Config.getELFConfig();
-    if (!ELFConfig)
-      return ELFConfig.takeError();
-
-    return elf::executeObjcopyOnBinary(Config.getCommonConfig(), *ELFConfig,
-                                       *ELFBinary, Out);
-  } else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In)) {
-    Expected<const COFFConfig &> COFFConfig = Config.getCOFFConfig();
-    if (!COFFConfig)
-      return COFFConfig.takeError();
-
-    return coff::executeObjcopyOnBinary(Config.getCommonConfig(), *COFFConfig,
-                                        *COFFBinary, Out);
-  } else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In)) {
-    Expected<const MachOConfig &> MachOConfig = Config.getMachOConfig();
-    if (!MachOConfig)
-      return MachOConfig.takeError();
-
-    return macho::executeObjcopyOnBinary(Config.getCommonConfig(), *MachOConfig,
-                                         *MachOBinary, Out);
-  } else if (auto *MachOUniversalBinary =
-                 dyn_cast<object::MachOUniversalBinary>(&In)) {
-    return macho::executeObjcopyOnMachOUniversalBinary(
-        Config, *MachOUniversalBinary, Out);
-  } else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In)) {
-    Expected<const WasmConfig &> WasmConfig = Config.getWasmConfig();
-    if (!WasmConfig)
-      return WasmConfig.takeError();
-
-    return objcopy::wasm::executeObjcopyOnBinary(Config.getCommonConfig(),
-                                                 *WasmConfig, *WasmBinary, Out);
-  } else
-    return createStringError(object_error::invalid_file_type,
-                             "unsupported object file format");
-}
-
-namespace llvm {
-namespace objcopy {
-
-Expected<std::vector<NewArchiveMember>>
-createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {
-  std::vector<NewArchiveMember> NewArchiveMembers;
-  Error Err = Error::success();
-  for (const Archive::Child &Child : Ar.children(Err)) {
-    Expected<StringRef> ChildNameOrErr = Child.getName();
-    if (!ChildNameOrErr)
-      return createFileError(Ar.getFileName(), ChildNameOrErr.takeError());
-
-    Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
-    if (!ChildOrErr)
-      return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",
-                             ChildOrErr.takeError());
-
-    SmallVector<char, 0> Buffer;
-    raw_svector_ostream MemStream(Buffer);
-
-    if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
-      return std::move(E);
-
-    Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
-        Child, Config.getCommonConfig().DeterministicArchives);
-    if (!Member)
-      return createFileError(Ar.getFileName(), Member.takeError());
-
-    Member->Buf = std::make_unique<SmallVectorMemoryBuffer>(
-        std::move(Buffer), ChildNameOrErr.get());
-    Member->MemberName = Member->Buf->getBufferIdentifier();
-    NewArchiveMembers.push_back(std::move(*Member));
-  }
-  if (Err)
-    return createFileError(Config.getCommonConfig().InputFilename,
-                           std::move(Err));
-  return std::move(NewArchiveMembers);
-}
-
-} // end namespace objcopy
-} // end namespace llvm
-
-static Error executeObjcopyOnArchive(const ConfigManager &ConfigMgr,
-                                     const object::Archive &Ar) {
-  Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
-      createNewArchiveMembers(ConfigMgr, Ar);
-  if (!NewArchiveMembersOrErr)
-    return NewArchiveMembersOrErr.takeError();
-  const CommonConfig &Config = ConfigMgr.getCommonConfig();
-  return deepWriteArchive(Config.OutputFilename, *NewArchiveMembersOrErr,
-                          Ar.hasSymbolTable(), Ar.kind(),
-                          Config.DeterministicArchives, Ar.isThin());
-}
-
 static Error restoreStatOnFile(StringRef Filename,
                                const sys::fs::file_status &Stat,
                                const ConfigManager &ConfigMgr) {
diff --git a/llvm/unittests/Object/CMakeLists.txt b/llvm/unittests/Object/CMakeLists.txt
--- a/llvm/unittests/Object/CMakeLists.txt
+++ b/llvm/unittests/Object/CMakeLists.txt
@@ -14,6 +14,7 @@
   SymbolSizeTest.cpp
   SymbolicFileTest.cpp
   XCOFFObjectFileTest.cpp
+  ObjCopyTest.cpp
   )
 
 target_link_libraries(ObjectTests PRIVATE LLVMTestingSupport)
diff --git a/llvm/unittests/Object/ObjCopyTest.cpp b/llvm/unittests/Object/ObjCopyTest.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/unittests/Object/ObjCopyTest.cpp
@@ -0,0 +1,125 @@
+//===- ObjCopyTest.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/ObjCopy/ObjCopy.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Object/ObjCopy/COFF/COFFObjcopy.h"
+#include "llvm/Object/ObjCopy/CommonConfig.h"
+#include "llvm/Object/ObjCopy/ConfigManager.h"
+#include "llvm/Object/ObjCopy/ELF/ELFConfig.h"
+#include "llvm/Object/ObjCopy/ELF/ELFObjcopy.h"
+#include "llvm/Object/ObjCopy/MachO/MachOObjcopy.h"
+#include "llvm/Object/ObjCopy/wasm/WasmObjcopy.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/Wasm.h"
+#include "llvm/ObjectYAML/yaml2obj.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace object;
+using namespace objcopy;
+using namespace yaml;
+
+void copySimpleFileImpl(const char *YamlCreationString,
+                        std::function<bool(const Binary &File)> IsValidFormat) {
+  auto ErrHandler = [&](const Twine &Msg) { FAIL() << "Error: " << Msg; };
+
+  // Create Object file from yaml description.
+  SmallString<0> Storage;
+  std::unique_ptr<ObjectFile> Obj =
+      yaml2ObjectFile(Storage, YamlCreationString, ErrHandler);
+  ASSERT_TRUE(Obj);
+  ASSERT_TRUE(IsValidFormat(*Obj));
+
+  // Reserve temporary name for the resulting file.
+  SmallString<64> Path;
+  int FD;
+  ASSERT_FALSE(sys::fs::createTemporaryFile("a", "out", FD, Path));
+  FileRemover Cleanup(Path);
+
+  ConfigManager Config;
+  Config.Common.OutputFilename = Path;
+
+  // Call executeObjcopyOnBinary()
+  std::error_code EC;
+  raw_fd_ostream OutStream(Config.Common.OutputFilename, EC);
+  Error Err = objcopy::executeObjcopyOnBinary(Config, *Obj.get(), OutStream);
+  OutStream.flush();
+  ASSERT_FALSE(std::move(Err));
+
+  // Load and check copied file.
+  Expected<OwningBinary<ObjectFile>> Result =
+      ObjectFile::createObjectFile(Config.Common.OutputFilename);
+  ASSERT_THAT_EXPECTED(Result, Succeeded());
+  ASSERT_TRUE(IsValidFormat(*Result->getBinary()));
+}
+
+TEST(CopySimpleFile, COFF) {
+  copySimpleFileImpl(
+      R"(
+--- !COFF
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: [  ]
+sections:
+  - Name:            .text
+    Characteristics: [  ]
+    Alignment:       4
+    SectionData:     E800000000C3C3C3
+symbols:
+...
+)",
+      [](const Binary &File) { return File.isCOFF(); });
+}
+
+TEST(CopySimpleFile, ELF) {
+  copySimpleFileImpl(
+      R"(
+--- !ELF
+FileHeader:
+   Class:    ELFCLASS64
+   Data:     ELFDATA2LSB
+   Type:     ET_REL)",
+      [](const Binary &File) { return File.isELF(); });
+}
+
+TEST(CopySimpleFile, MachO) {
+  copySimpleFileImpl(
+      R"(
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x80000003
+  filetype:        0x00000002
+  ncmds:           0
+  sizeofcmds:      0
+  flags:           0x00218085
+  reserved:        0x00000000
+...
+)",
+      [](const Binary &File) { return File.isMachO(); });
+}
+
+TEST(CopySimpleFile, Wasm) {
+  copySimpleFileImpl(
+      R"(
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+...
+)",
+      [](const Binary &File) { return File.isWasm(); });
+}