diff --git a/llvm/tools/llvm-objcopy/Buffer.h b/llvm/include/llvm/ObjCopy/Buffer.h rename from llvm/tools/llvm-objcopy/Buffer.h rename to llvm/include/llvm/ObjCopy/Buffer.h --- a/llvm/tools/llvm-objcopy/Buffer.h +++ b/llvm/include/llvm/ObjCopy/Buffer.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_BUFFER_H -#define LLVM_TOOLS_OBJCOPY_BUFFER_H +#ifndef LLVM_OBJCOPY_BUFFER_H +#define LLVM_OBJCOPY_BUFFER_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileOutputBuffer.h" @@ -65,4 +65,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_OBJCOPY_BUFFER_H +#endif // LLVM_OBJCOPY_BUFFER_H diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h b/llvm/include/llvm/ObjCopy/COFF/COFFObjcopy.h rename from llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h rename to llvm/include/llvm/ObjCopy/COFF/COFFObjcopy.h --- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h +++ b/llvm/include/llvm/ObjCopy/COFF/COFFObjcopy.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H -#define LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H +#ifndef LLVM_OBJCOPY_COFF_COFFOBJCOPY_H +#define LLVM_OBJCOPY_COFF_COFFOBJCOPY_H namespace llvm { class Error; @@ -28,4 +28,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H +#endif // LLVM_OBJCOPY_COFF_COFFOBJCOPY_H diff --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/include/llvm/ObjCopy/CopyConfig.h rename from llvm/tools/llvm-objcopy/CopyConfig.h rename to llvm/include/llvm/ObjCopy/CopyConfig.h --- a/llvm/tools/llvm-objcopy/CopyConfig.h +++ b/llvm/include/llvm/ObjCopy/CopyConfig.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H -#define LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H +#ifndef LLVM_OBJCOPY_COPYCONFIG_H +#define LLVM_OBJCOPY_COPYCONFIG_H #include "ELF/ELFConfig.h" #include "llvm/ADT/ArrayRef.h" @@ -245,41 +245,7 @@ } }; -// 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. -struct DriverConfig { - SmallVector CopyConfigs; - BumpPtrAllocator Alloc; -}; - -// ParseObjcopyOptions returns the config and sets the input arguments. If a -// help flag is set then ParseObjcopyOptions will print the help messege and -// exit. ErrorCallback is used to handle recoverable errors. An Error returned -// by the callback aborts the parsing and is then returned by this function. -Expected -parseObjcopyOptions(ArrayRef ArgsArr, - llvm::function_ref ErrorCallback); - -// ParseInstallNameToolOptions returns the config and sets the input arguments. -// If a help flag is set then ParseInstallNameToolOptions will print the help -// messege and exit. -Expected -parseInstallNameToolOptions(ArrayRef ArgsArr); - -// ParseBitcodeStripOptions returns the config and sets the input arguments. -// If a help flag is set then ParseBitcodeStripOptions will print the help -// messege and exit. -Expected parseBitcodeStripOptions(ArrayRef ArgsArr); - -// ParseStripOptions returns the config and sets the input arguments. If a -// help flag is set then ParseStripOptions will print the help messege and -// exit. ErrorCallback is used to handle recoverable errors. An Error returned -// by the callback aborts the parsing and is then returned by this function. -Expected -parseStripOptions(ArrayRef ArgsArr, - llvm::function_ref ErrorCallback); } // namespace objcopy } // namespace llvm -#endif +#endif // LLVM_OBJCOPY_COPYCONFIG_H diff --git a/llvm/tools/llvm-objcopy/ELF/ELFConfig.h b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h rename from llvm/tools/llvm-objcopy/ELF/ELFConfig.h rename to llvm/include/llvm/ObjCopy/ELF/ELFConfig.h --- a/llvm/tools/llvm-objcopy/ELF/ELFConfig.h +++ b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_ELFCONFIG_H -#define LLVM_TOOLS_OBJCOPY_ELFCONFIG_H +#ifndef LLVM_OBJCOPY_ELF_ELFCONFIG_H +#define LLVM_OBJCOPY_ELF_ELFCONFIG_H #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" @@ -41,4 +41,4 @@ } // namespace objcopy } // namespace llvm -#endif +#endif // LLVM_OBJCOPY_ELF_ELFCONFIG_H diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h b/llvm/include/llvm/ObjCopy/ELF/ELFObjcopy.h rename from llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h rename to llvm/include/llvm/ObjCopy/ELF/ELFObjcopy.h --- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h +++ b/llvm/include/llvm/ObjCopy/ELF/ELFObjcopy.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H -#define LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H +#ifndef LLVM_OBJCOPY_ELF_ELFOBJCOPY_H +#define LLVM_OBJCOPY_ELF_ELFOBJCOPY_H namespace llvm { class Error; @@ -33,4 +33,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H +#endif // LLVM_OBJCOPY_ELF_ELFOBJCOPY_H diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h b/llvm/include/llvm/ObjCopy/MachO/MachOObjcopy.h rename from llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h rename to llvm/include/llvm/ObjCopy/MachO/MachOObjcopy.h --- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h +++ b/llvm/include/llvm/ObjCopy/MachO/MachOObjcopy.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H -#define LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H +#ifndef LLVM_OBJCOPY_MACHO_MACHOOBJCOPY_H +#define LLVM_OBJCOPY_MACHO_MACHOOBJCOPY_H namespace llvm { class Error; @@ -32,4 +32,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H +#endif // LLVM_OBJCOPY_MACHO_MACHOOBJCOPY_H diff --git a/llvm/include/llvm/ObjCopy/ObjCopy.h b/llvm/include/llvm/ObjCopy/ObjCopy.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/ObjCopy/ObjCopy.h @@ -0,0 +1,34 @@ +//===- 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_OBJCOPY_OBJCOPY_H +#define LLVM_OBJCOPY_OBJCOPY_H + +#include "Buffer.h" +#include "CopyConfig.h" +#include "llvm/Object/Archive.h" + +namespace llvm { +namespace objcopy { + +/// The function applies transformation described by Config to +/// the specified binary and writes result into the Out. It does +/// the dispatch based on the format of the input binary +/// (ELF, MachO or COFF). +Error executeObjcopyOnBinary(CopyConfig &Config, object::Binary &In, + Buffer &Out); + +/// The function applies transformation described by Config to +/// the specified archive. It does the dispatch based on the format +/// of the input binary (ELF, MachO or COFF). +Error executeObjcopyOnArchive(CopyConfig &Config, const object::Archive &Ar); + +} // end namespace objcopy +} // end namespace llvm + +#endif // LLVM_OBJCOPY_OBJCOPY_H diff --git a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h b/llvm/include/llvm/ObjCopy/wasm/WasmObjcopy.h rename from llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h rename to llvm/include/llvm/ObjCopy/wasm/WasmObjcopy.h --- a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h +++ b/llvm/include/llvm/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_OBJCOPY_WASM_WASMOBJCOPY_H +#define LLVM_OBJCOPY_WASM_WASMOBJCOPY_H namespace llvm { class Error; @@ -28,4 +28,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMOBJCOPY_H +#endif // LLVM_OBJCOPY_WASM_WASMOBJCOPY_H diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt --- a/llvm/lib/CMakeLists.txt +++ b/llvm/lib/CMakeLists.txt @@ -20,6 +20,7 @@ add_subdirectory(MC) add_subdirectory(MCA) add_subdirectory(Object) +add_subdirectory(ObjCopy) add_subdirectory(ObjectYAML) add_subdirectory(Option) add_subdirectory(Remarks) diff --git a/llvm/lib/LLVMBuild.txt b/llvm/lib/LLVMBuild.txt --- a/llvm/lib/LLVMBuild.txt +++ b/llvm/lib/LLVMBuild.txt @@ -37,6 +37,7 @@ MC MCA Object + ObjCopy BinaryFormat ObjectYAML Option diff --git a/llvm/tools/llvm-objcopy/Buffer.cpp b/llvm/lib/ObjCopy/Buffer.cpp rename from llvm/tools/llvm-objcopy/Buffer.cpp rename to llvm/lib/ObjCopy/Buffer.cpp --- a/llvm/tools/llvm-objcopy/Buffer.cpp +++ b/llvm/lib/ObjCopy/Buffer.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "Buffer.h" +#include "llvm/ObjCopy/Buffer.h" #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/llvm/lib/ObjCopy/CMakeLists.txt b/llvm/lib/ObjCopy/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/llvm/lib/ObjCopy/CMakeLists.txt @@ -0,0 +1,27 @@ +add_llvm_component_library(LLVMObjCopy + Buffer.cpp + CopyConfig.cpp + ObjCopy.cpp + COFF/COFFObjcopy.cpp + COFF/Object.cpp + COFF/Reader.cpp + COFF/Writer.cpp + ELF/ELFConfig.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 + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy + + DEPENDS + intrinsics_gen + ) diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp rename from llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp rename to llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp --- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ b/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// -#include "COFFObjcopy.h" -#include "Buffer.h" -#include "CopyConfig.h" +#include "llvm/ObjCopy/COFF/COFFObjcopy.h" #include "Object.h" #include "Reader.h" #include "Writer.h" +#include "llvm/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/CopyConfig.h" #include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/lib/ObjCopy/COFF/Object.h rename from llvm/tools/llvm-objcopy/COFF/Object.h rename to llvm/lib/ObjCopy/COFF/Object.h --- a/llvm/tools/llvm-objcopy/COFF/Object.h +++ b/llvm/lib/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_OBJCOPY_COFF_OBJECT_H +#define LLVM_LIB_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_OBJCOPY_COFF_OBJECT_H diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/lib/ObjCopy/COFF/Object.cpp rename from llvm/tools/llvm-objcopy/COFF/Object.cpp rename to llvm/lib/ObjCopy/COFF/Object.cpp diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.h b/llvm/lib/ObjCopy/COFF/Reader.h rename from llvm/tools/llvm-objcopy/COFF/Reader.h rename to llvm/lib/ObjCopy/COFF/Reader.h --- a/llvm/tools/llvm-objcopy/COFF/Reader.h +++ b/llvm/lib/ObjCopy/COFF/Reader.h @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_COFF_READER_H -#define LLVM_TOOLS_OBJCOPY_COFF_READER_H +#ifndef LLVM_LIB_OBJCOPY_COFF_READER_H +#define LLVM_LIB_OBJCOPY_COFF_READER_H -#include "Buffer.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/ObjCopy/Buffer.h" #include "llvm/Object/COFF.h" #include "llvm/Support/Error.h" @@ -39,4 +39,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_OBJCOPY_COFF_READER_H +#endif // LLVM_LIB_OBJCOPY_COFF_READER_H diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/lib/ObjCopy/COFF/Reader.cpp rename from llvm/tools/llvm-objcopy/COFF/Reader.cpp rename to llvm/lib/ObjCopy/COFF/Reader.cpp diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/lib/ObjCopy/COFF/Writer.h rename from llvm/tools/llvm-objcopy/COFF/Writer.h rename to llvm/lib/ObjCopy/COFF/Writer.h --- a/llvm/tools/llvm-objcopy/COFF/Writer.h +++ b/llvm/lib/ObjCopy/COFF/Writer.h @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_COFF_WRITER_H -#define LLVM_TOOLS_OBJCOPY_COFF_WRITER_H +#ifndef LLVM_LIB_OBJCOPY_COFF_WRITER_H +#define LLVM_LIB_OBJCOPY_COFF_WRITER_H -#include "Buffer.h" #include "llvm/MC/StringTableBuilder.h" +#include "llvm/ObjCopy/Buffer.h" #include "llvm/Support/Error.h" #include #include @@ -59,4 +59,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_OBJCOPY_COFF_WRITER_H +#endif // LLVM_LIB_OBJCOPY_COFF_WRITER_H diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/lib/ObjCopy/COFF/Writer.cpp rename from llvm/tools/llvm-objcopy/COFF/Writer.cpp rename to llvm/lib/ObjCopy/COFF/Writer.cpp diff --git a/llvm/lib/ObjCopy/CopyConfig.cpp b/llvm/lib/ObjCopy/CopyConfig.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/ObjCopy/CopyConfig.cpp @@ -0,0 +1,50 @@ +//===- CopyConfig.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/ObjCopy/CopyConfig.h" + +namespace llvm { +namespace objcopy { + +Expected +NameOrPattern::create(StringRef Pattern, MatchStyle MS, + llvm::function_ref ErrorCallback) { + switch (MS) { + case MatchStyle::Literal: + return NameOrPattern(Pattern); + case MatchStyle::Wildcard: { + SmallVector Data; + bool IsPositiveMatch = true; + if (Pattern[0] == '!') { + IsPositiveMatch = false; + Pattern = Pattern.drop_front(); + } + Expected GlobOrErr = GlobPattern::create(Pattern); + + // If we couldn't create it as a glob, report the error, but try again with + // a literal if the error reporting is non-fatal. + if (!GlobOrErr) { + if (Error E = ErrorCallback(GlobOrErr.takeError())) + return std::move(E); + return create(Pattern, MatchStyle::Literal, ErrorCallback); + } + + return NameOrPattern(std::make_shared(*GlobOrErr), + IsPositiveMatch); + } + case MatchStyle::Regex: { + SmallVector Data; + return NameOrPattern(std::make_shared( + ("^" + Pattern.ltrim('^').rtrim('$') + "$").toStringRef(Data))); + } + } + llvm_unreachable("Unhandled llvm.objcopy.MatchStyle enum"); +} + +} // namespace objcopy +} // namespace llvm diff --git a/llvm/tools/llvm-objcopy/ELF/ELFConfig.cpp b/llvm/lib/ObjCopy/ELF/ELFConfig.cpp rename from llvm/tools/llvm-objcopy/ELF/ELFConfig.cpp rename to llvm/lib/ObjCopy/ELF/ELFConfig.cpp --- a/llvm/tools/llvm-objcopy/ELF/ELFConfig.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFConfig.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// -#include "CopyConfig.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ObjCopy/CopyConfig.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp rename from llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp rename to llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp --- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp @@ -6,9 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "ELFObjcopy.h" -#include "Buffer.h" -#include "CopyConfig.h" +#include "llvm/ObjCopy/ELF/ELFObjcopy.h" #include "Object.h" #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/DenseSet.h" @@ -19,6 +17,8 @@ #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/CopyConfig.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ELFTypes.h" diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/lib/ObjCopy/ELF/Object.h rename from llvm/tools/llvm-objcopy/ELF/Object.h rename to llvm/lib/ObjCopy/ELF/Object.h --- a/llvm/tools/llvm-objcopy/ELF/Object.h +++ b/llvm/lib/ObjCopy/ELF/Object.h @@ -6,16 +6,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_OBJECT_H -#define LLVM_TOOLS_OBJCOPY_OBJECT_H +#ifndef LLVM_LIB_OBJCOPY_ELF_OBJECT_H +#define LLVM_LIB_OBJCOPY_ELF_OBJECT_H -#include "Buffer.h" -#include "CopyConfig.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/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/CopyConfig.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FileOutputBuffer.h" @@ -1097,4 +1097,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_OBJCOPY_OBJECT_H +#endif // LLVM_LIB_OBJCOPY_ELF_OBJECT_H diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/lib/ObjCopy/ELF/Object.cpp rename from llvm/tools/llvm-objcopy/ELF/Object.cpp rename to llvm/lib/ObjCopy/ELF/Object.cpp diff --git a/llvm/lib/LLVMBuild.txt b/llvm/lib/ObjCopy/LLVMBuild.txt copy from llvm/lib/LLVMBuild.txt copy to llvm/lib/ObjCopy/LLVMBuild.txt --- a/llvm/lib/LLVMBuild.txt +++ b/llvm/lib/ObjCopy/LLVMBuild.txt @@ -1,4 +1,4 @@ -;===- ./lib/LLVMBuild.txt --------------------------------------*- Conf -*--===; +;===- ./lib/ObjCopy/LLVMBuild.txt -----------------------------*- Conf -*--===; ; ; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ; See https://llvm.org/LICENSE.txt for license information. @@ -14,46 +14,8 @@ ; ;===------------------------------------------------------------------------===; -[common] -subdirectories = - Analysis - AsmParser - Bitcode - Bitstream - CodeGen - DebugInfo - Demangle - DWARFLinker - ExecutionEngine - Extensions - Frontend - FuzzMutate - LineEditor - Linker - InterfaceStub - IR - IRReader - LTO - MC - MCA - Object - BinaryFormat - ObjectYAML - Option - Remarks - Passes - ProfileData - Support - TableGen - TextAPI - Target - Testing - ToolDrivers - Transforms - WindowsManifest - XRay - [component_0] -type = Group -name = Libraries -parent = $ROOT +type = Library +name = ObjCopy +parent = Libraries +required_libraries = Object Support MC diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.h rename from llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h rename to llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.h --- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h +++ b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.h @@ -9,8 +9,8 @@ #ifndef LLVM_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H #define LLVM_OBJCOPY_MACHO_MACHOLAYOUTBUILDER_H -#include "MachOObjcopy.h" #include "Object.h" +#include "llvm/ObjCopy/MachO/MachOObjcopy.h" namespace llvm { namespace objcopy { diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp rename from llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp rename to llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp rename from llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp rename to llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp @@ -6,17 +6,18 @@ // //===----------------------------------------------------------------------===// -#include "MachOObjcopy.h" -#include "../CopyConfig.h" -#include "../llvm-objcopy.h" +#include "llvm/ObjCopy/MachO/MachOObjcopy.h" #include "MachOReader.h" #include "MachOWriter.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ObjCopy/CopyConfig.h" +#include "llvm/ObjCopy/ObjCopy.h" #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/MachOUniversalWriter.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" +#include "Util.h" namespace llvm { namespace objcopy { @@ -437,7 +438,7 @@ } std::string ArchFlagName = O.getArchFlagName(); MemBuffer MB(ArchFlagName); - if (Error E = executeObjcopyOnBinary(Config, **ObjOrErr, MB)) + if (Error E = objcopy::executeObjcopyOnBinary(Config, **ObjOrErr, MB)) return E; std::unique_ptr OutputBuffer = MB.releaseMemoryBuffer(); diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.h b/llvm/lib/ObjCopy/MachO/MachOReader.h rename from llvm/tools/llvm-objcopy/MachO/MachOReader.h rename to llvm/lib/ObjCopy/MachO/MachOReader.h --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.h +++ b/llvm/lib/ObjCopy/MachO/MachOReader.h @@ -6,9 +6,12 @@ // //===----------------------------------------------------------------------===// -#include "MachOObjcopy.h" +#ifndef LLVM_LIB_OBJCOPY_MACHO_MACHOREADER_H +#define LLVM_LIB_OBJCOPY_MACHO_MACHOREADER_H + #include "Object.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/ObjCopy/MachO/MachOObjcopy.h" #include "llvm/Object/MachO.h" #include @@ -52,3 +55,5 @@ } // end namespace macho } // end namespace objcopy } // end namespace llvm + +#endif // LLVM_LIB_OBJCOPY_MACHO_MACHOREADER_H diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/lib/ObjCopy/MachO/MachOReader.cpp rename from llvm/tools/llvm-objcopy/MachO/MachOReader.cpp rename to llvm/lib/ObjCopy/MachO/MachOReader.cpp diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.h b/llvm/lib/ObjCopy/MachO/MachOWriter.h rename from llvm/tools/llvm-objcopy/MachO/MachOWriter.h rename to llvm/lib/ObjCopy/MachO/MachOWriter.h --- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.h +++ b/llvm/lib/ObjCopy/MachO/MachOWriter.h @@ -6,11 +6,14 @@ // //===----------------------------------------------------------------------===// -#include "../Buffer.h" +#ifndef LLVM_LIB_OBJCOPY_MACHO_MACHOWRITER_H +#define LLVM_LIB_OBJCOPY_MACHO_MACHOWRITER_H + #include "MachOLayoutBuilder.h" -#include "MachOObjcopy.h" #include "Object.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/MachO/MachOObjcopy.h" #include "llvm/Object/MachO.h" namespace llvm { @@ -65,3 +68,5 @@ } // end namespace macho } // end namespace objcopy } // end namespace llvm + +#endif // LLVM_LIB_OBJCOPY_MACHO_MACHOWRITER_H diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp b/llvm/lib/ObjCopy/MachO/MachOWriter.cpp rename from llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp rename to llvm/lib/ObjCopy/MachO/MachOWriter.cpp diff --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/lib/ObjCopy/MachO/Object.h rename from llvm/tools/llvm-objcopy/MachO/Object.h rename to llvm/lib/ObjCopy/MachO/Object.h diff --git a/llvm/tools/llvm-objcopy/MachO/Object.cpp b/llvm/lib/ObjCopy/MachO/Object.cpp rename from llvm/tools/llvm-objcopy/MachO/Object.cpp rename to llvm/lib/ObjCopy/MachO/Object.cpp diff --git a/llvm/lib/ObjCopy/ObjCopy.cpp b/llvm/lib/ObjCopy/ObjCopy.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/ObjCopy/ObjCopy.cpp @@ -0,0 +1,131 @@ +//===- Util.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/ObjCopy/ObjCopy.h" +#include "llvm/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/COFF/COFFObjcopy.h" +#include "llvm/ObjCopy/ELF/ELFObjcopy.h" +#include "llvm/ObjCopy/MachO/MachOObjcopy.h" +#include "llvm/ObjCopy/wasm/WasmObjcopy.h" +#include "llvm/Object/ArchiveWriter.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/MachOUniversal.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Wasm.h" +#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" +#include "Util.h" +#include + +using namespace llvm; +using namespace llvm::object; + +namespace llvm { +namespace objcopy { + +Error executeObjcopyOnBinary(CopyConfig &Config, object::Binary &In, + Buffer &Out) { + if (auto *ELFBinary = dyn_cast(&In)) { + if (Error E = Config.parseELFConfig()) + return E; + return elf::executeObjcopyOnBinary(Config, *ELFBinary, Out); + } else if (auto *COFFBinary = dyn_cast(&In)) + return coff::executeObjcopyOnBinary(Config, *COFFBinary, Out); + else if (auto *MachOBinary = dyn_cast(&In)) + return macho::executeObjcopyOnBinary(Config, *MachOBinary, Out); + else if (auto *MachOUniversalBinary = + dyn_cast(&In)) + return macho::executeObjcopyOnMachOUniversalBinary( + Config, *MachOUniversalBinary, Out); + else if (auto *WasmBinary = dyn_cast(&In)) + return objcopy::wasm::executeObjcopyOnBinary(Config, *WasmBinary, Out); + else + return createStringError(object_error::invalid_file_type, + "unsupported object file format"); +} + +Expected> +createNewArchiveMembers(CopyConfig &Config, const Archive &Ar) { + std::vector NewArchiveMembers; + Error Err = Error::success(); + for (const Archive::Child &Child : Ar.children(Err)) { + Expected ChildNameOrErr = Child.getName(); + if (!ChildNameOrErr) + return createFileError(Ar.getFileName(), ChildNameOrErr.takeError()); + + Expected> ChildOrErr = Child.getAsBinary(); + if (!ChildOrErr) + return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")", + ChildOrErr.takeError()); + + MemBuffer MB(ChildNameOrErr.get()); + if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MB)) + return std::move(E); + + Expected Member = + NewArchiveMember::getOldMember(Child, Config.DeterministicArchives); + if (!Member) + return createFileError(Ar.getFileName(), Member.takeError()); + Member->Buf = MB.releaseMemoryBuffer(); + Member->MemberName = Member->Buf->getBufferIdentifier(); + NewArchiveMembers.push_back(std::move(*Member)); + } + if (Err) + return createFileError(Config.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 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) { + // Internally, FileBuffer will use the buffer created by + // FileOutputBuffer::create, for regular files (that 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. + FileBuffer FB(Member.MemberName); + if (Error E = FB.allocate(Member.Buf->getBufferSize())) + return E; + std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(), + FB.getBufferStart()); + if (Error E = FB.commit()) + return E; + } + return Error::success(); +} + +Error executeObjcopyOnArchive(CopyConfig &Config, const object::Archive &Ar) { + Expected> NewArchiveMembersOrErr = + createNewArchiveMembers(Config, Ar); + if (!NewArchiveMembersOrErr) + return NewArchiveMembersOrErr.takeError(); + return deepWriteArchive(Config.OutputFilename, *NewArchiveMembersOrErr, + Ar.hasSymbolTable(), Ar.kind(), + Config.DeterministicArchives, Ar.isThin()); +} + +} // end namespace objcopy +} // end namespace llvm diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.h b/llvm/lib/ObjCopy/Util.h rename from llvm/tools/llvm-objcopy/llvm-objcopy.h rename to llvm/lib/ObjCopy/Util.h --- a/llvm/tools/llvm-objcopy/llvm-objcopy.h +++ b/llvm/lib/ObjCopy/Util.h @@ -1,4 +1,4 @@ -//===- llvm-objcopy.h -------------------------------------------*- C++ -*-===// +//===- Util.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. @@ -6,27 +6,21 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJCOPY_OBJCOPY_H -#define LLVM_TOOLS_OBJCOPY_OBJCOPY_H +#ifndef LLVM_LIB_OBJCOPY_UTIL_H +#define LLVM_LIB_OBJCOPY_UTIL_H -#include "llvm/Support/Error.h" +#include "llvm/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/CopyConfig.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/ArchiveWriter.h" namespace llvm { - -struct NewArchiveMember; - -namespace object { - -class Archive; - -} // end namespace object - namespace objcopy { -struct CopyConfig; + Expected> createNewArchiveMembers(CopyConfig &Config, const object::Archive &Ar); } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_OBJCOPY_OBJCOPY_H +#endif // LLVM_LIB_OBJCOPY_UTIL_H diff --git a/llvm/tools/llvm-objcopy/wasm/Object.h b/llvm/lib/ObjCopy/wasm/Object.h rename from llvm/tools/llvm-objcopy/wasm/Object.h rename to llvm/lib/ObjCopy/wasm/Object.h --- a/llvm/tools/llvm-objcopy/wasm/Object.h +++ b/llvm/lib/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_OBJCOPY_WASM_OBJECT_H +#define LLVM_LIB_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_OBJCOPY_WASM_OBJECT_H diff --git a/llvm/tools/llvm-objcopy/wasm/Object.cpp b/llvm/lib/ObjCopy/wasm/Object.cpp rename from llvm/tools/llvm-objcopy/wasm/Object.cpp rename to llvm/lib/ObjCopy/wasm/Object.cpp diff --git a/llvm/tools/llvm-objcopy/wasm/Reader.h b/llvm/lib/ObjCopy/wasm/Reader.h rename from llvm/tools/llvm-objcopy/wasm/Reader.h rename to llvm/lib/ObjCopy/wasm/Reader.h --- a/llvm/tools/llvm-objcopy/wasm/Reader.h +++ b/llvm/lib/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_LLVM_OBJCOPY_WASM_READER_H +#define LLVM_LIB_LLVM_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_LLVM_OBJCOPY_WASM_READER_H diff --git a/llvm/tools/llvm-objcopy/wasm/Reader.cpp b/llvm/lib/ObjCopy/wasm/Reader.cpp rename from llvm/tools/llvm-objcopy/wasm/Reader.cpp rename to llvm/lib/ObjCopy/wasm/Reader.cpp diff --git a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp b/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp rename from llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp rename to llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp --- a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp +++ b/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// -#include "WasmObjcopy.h" -#include "Buffer.h" -#include "CopyConfig.h" +#include "llvm/ObjCopy/wasm/WasmObjcopy.h" #include "Object.h" #include "Reader.h" #include "Writer.h" +#include "llvm/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/CopyConfig.h" #include "llvm/Support/Errc.h" namespace llvm { diff --git a/llvm/tools/llvm-objcopy/wasm/Writer.h b/llvm/lib/ObjCopy/wasm/Writer.h rename from llvm/tools/llvm-objcopy/wasm/Writer.h rename to llvm/lib/ObjCopy/wasm/Writer.h --- a/llvm/tools/llvm-objcopy/wasm/Writer.h +++ b/llvm/lib/ObjCopy/wasm/Writer.h @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_WRITER_H -#define LLVM_TOOLS_LLVM_OBJCOPY_WASM_WRITER_H +#ifndef LLVM_LIB_OBJCOPY_WASM_WRITER_H +#define LLVM_LIB_OBJCOPY_WASM_WRITER_H -#include "Buffer.h" #include "Object.h" +#include "llvm/ObjCopy/Buffer.h" #include #include @@ -47,4 +47,4 @@ } // end namespace objcopy } // end namespace llvm -#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_WRITER_H +#endif // LLVM_LIB_OBJCOPY_WASM_WRITER_H diff --git a/llvm/tools/llvm-objcopy/wasm/Writer.cpp b/llvm/lib/ObjCopy/wasm/Writer.cpp rename from llvm/tools/llvm-objcopy/wasm/Writer.cpp rename to llvm/lib/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 @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS Object + ObjCopy Option Support MC @@ -22,25 +23,8 @@ add_public_tablegen_target(StripOptsTableGen) add_llvm_tool(llvm-objcopy - Buffer.cpp - CopyConfig.cpp llvm-objcopy.cpp - COFF/COFFObjcopy.cpp - COFF/Object.cpp - COFF/Reader.cpp - COFF/Writer.cpp - ELF/ELFConfig.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 + ParseConfig.cpp DEPENDS ObjcopyOptsTableGen InstallNameToolOptsTableGen diff --git a/llvm/tools/llvm-objcopy/ParseConfig.h b/llvm/tools/llvm-objcopy/ParseConfig.h new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-objcopy/ParseConfig.h @@ -0,0 +1,60 @@ +//===- ParseConfig.h ------------------------------------------------------===// +// +// 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_LLVM_OBJCOPY_PARSECONFIG_H +#define LLVM_TOOLS_LLVM_OBJCOPY_PARSECONFIG_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ObjCopy/CopyConfig.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/GlobPattern.h" +#include "llvm/Support/Regex.h" + +namespace llvm { +namespace objcopy { + +// 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. +struct DriverConfig { + SmallVector CopyConfigs; + BumpPtrAllocator Alloc; +}; + +// ParseObjcopyOptions returns the config and sets the input arguments. If a +// help flag is set then ParseObjcopyOptions will print the help messege and +// exit. ErrorCallback is used to handle recoverable errors. An Error returned +// by the callback aborts the parsing and is then returned by this function. +Expected +parseObjcopyOptions(ArrayRef ArgsArr, + llvm::function_ref ErrorCallback); + +// ParseInstallNameToolOptions returns the config and sets the input arguments. +// If a help flag is set then ParseInstallNameToolOptions will print the help +// messege and exit. +Expected +parseInstallNameToolOptions(ArrayRef ArgsArr); + +// ParseBitcodeStripOptions returns the config and sets the input arguments. +// If a help flag is set then ParseBitcodeStripOptions will print the help +// messege and exit. +Expected parseBitcodeStripOptions(ArrayRef ArgsArr); + +// ParseStripOptions returns the config and sets the input arguments. If a +// help flag is set then ParseStripOptions will print the help messege and +// exit. ErrorCallback is used to handle recoverable errors. An Error returned +// by the callback aborts the parsing and is then returned by this function. +Expected +parseStripOptions(ArrayRef ArgsArr, + llvm::function_ref ErrorCallback); + +} // namespace objcopy +} // namespace llvm + +#endif // LLVM_TOOLS_LLVM_OBJCOPY_PARSECONFIG_H diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/ParseConfig.cpp rename from llvm/tools/llvm-objcopy/CopyConfig.cpp rename to llvm/tools/llvm-objcopy/ParseConfig.cpp --- a/llvm/tools/llvm-objcopy/CopyConfig.cpp +++ b/llvm/tools/llvm-objcopy/ParseConfig.cpp @@ -1,4 +1,4 @@ -//===- CopyConfig.cpp -----------------------------------------------------===// +//===- ParseConfig.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,8 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "CopyConfig.h" - +#include "ParseConfig.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -244,9 +243,10 @@ "bad format for --set-section-alignment: missing section name"); uint64_t NewAlign; if (Split.second.getAsInteger(0, NewAlign)) - return createStringError(errc::invalid_argument, - "invalid alignment for --set-section-alignment: '%s'", - Split.second.str().c_str()); + return createStringError( + errc::invalid_argument, + "invalid alignment for --set-section-alignment: '%s'", + Split.second.str().c_str()); return std::make_pair(Split.first, NewAlign); } @@ -361,41 +361,6 @@ return Error::success(); } -Expected -NameOrPattern::create(StringRef Pattern, MatchStyle MS, - llvm::function_ref ErrorCallback) { - switch (MS) { - case MatchStyle::Literal: - return NameOrPattern(Pattern); - case MatchStyle::Wildcard: { - SmallVector Data; - bool IsPositiveMatch = true; - if (Pattern[0] == '!') { - IsPositiveMatch = false; - Pattern = Pattern.drop_front(); - } - Expected GlobOrErr = GlobPattern::create(Pattern); - - // If we couldn't create it as a glob, report the error, but try again with - // a literal if the error reporting is non-fatal. - if (!GlobOrErr) { - if (Error E = ErrorCallback(GlobOrErr.takeError())) - return std::move(E); - return create(Pattern, MatchStyle::Literal, ErrorCallback); - } - - return NameOrPattern(std::make_shared(*GlobOrErr), - IsPositiveMatch); - } - case MatchStyle::Regex: { - SmallVector Data; - return NameOrPattern(std::make_shared( - ("^" + Pattern.ltrim('^').rtrim('$') + "$").toStringRef(Data))); - } - } - llvm_unreachable("Unhandled llvm.objcopy.MatchStyle enum"); -} - static Error addSymbolsToRenameFromFile(StringMap &SymbolsToRename, BumpPtrAllocator &Alloc, StringRef Filename) { 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,18 @@ // //===----------------------------------------------------------------------===// -#include "Buffer.h" -#include "COFF/COFFObjcopy.h" -#include "CopyConfig.h" -#include "ELF/ELFObjcopy.h" -#include "MachO/MachOObjcopy.h" -#include "wasm/WasmObjcopy.h" - +#include "ParseConfig.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/COFF/COFFObjcopy.h" +#include "llvm/ObjCopy/CopyConfig.h" +#include "llvm/ObjCopy/ELF/ELFObjcopy.h" +#include "llvm/ObjCopy/MachO/MachOObjcopy.h" +#include "llvm/ObjCopy/ObjCopy.h" +#include "llvm/ObjCopy/wasm/WasmObjcopy.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/Binary.h" @@ -70,39 +71,6 @@ 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, - ArrayRef 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) { - // Internally, FileBuffer will use the buffer created by - // FileOutputBuffer::create, for regular files (that 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. - FileBuffer FB(Member.MemberName); - if (Error E = FB.allocate(Member.Buf->getBufferSize())) - return E; - 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(CopyConfig &Config, MemoryBuffer &In, @@ -133,77 +101,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(CopyConfig &Config, object::Binary &In, - Buffer &Out) { - if (auto *ELFBinary = dyn_cast(&In)) { - if (Error E = Config.parseELFConfig()) - return E; - return elf::executeObjcopyOnBinary(Config, *ELFBinary, Out); - } else if (auto *COFFBinary = dyn_cast(&In)) - return coff::executeObjcopyOnBinary(Config, *COFFBinary, Out); - else if (auto *MachOBinary = dyn_cast(&In)) - return macho::executeObjcopyOnBinary(Config, *MachOBinary, Out); - else if (auto *MachOUniversalBinary = - dyn_cast(&In)) - return macho::executeObjcopyOnMachOUniversalBinary( - Config, *MachOUniversalBinary, Out); - else if (auto *WasmBinary = dyn_cast(&In)) - return objcopy::wasm::executeObjcopyOnBinary(Config, *WasmBinary, Out); - else - return createStringError(object_error::invalid_file_type, - "unsupported object file format"); -} - -namespace llvm { -namespace objcopy { - -Expected> -createNewArchiveMembers(CopyConfig &Config, const Archive &Ar) { - std::vector NewArchiveMembers; - Error Err = Error::success(); - for (const Archive::Child &Child : Ar.children(Err)) { - Expected ChildNameOrErr = Child.getName(); - if (!ChildNameOrErr) - return createFileError(Ar.getFileName(), ChildNameOrErr.takeError()); - - Expected> ChildOrErr = Child.getAsBinary(); - if (!ChildOrErr) - return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")", - ChildOrErr.takeError()); - - MemBuffer MB(ChildNameOrErr.get()); - if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MB)) - return std::move(E); - - Expected Member = - NewArchiveMember::getOldMember(Child, Config.DeterministicArchives); - if (!Member) - return createFileError(Ar.getFileName(), Member.takeError()); - Member->Buf = MB.releaseMemoryBuffer(); - Member->MemberName = Member->Buf->getBufferIdentifier(); - NewArchiveMembers.push_back(std::move(*Member)); - } - if (Err) - return createFileError(Config.InputFilename, std::move(Err)); - return std::move(NewArchiveMembers); -} - -} // end namespace objcopy -} // end namespace llvm - -static Error executeObjcopyOnArchive(CopyConfig &Config, - const object::Archive &Ar) { - Expected> NewArchiveMembersOrErr = - createNewArchiveMembers(Config, Ar); - if (!NewArchiveMembersOrErr) - return NewArchiveMembersOrErr.takeError(); - return deepWriteArchive(Config.OutputFilename, *NewArchiveMembersOrErr, - Ar.hasSymbolTable(), Ar.kind(), - Config.DeterministicArchives, Ar.isThin()); -} - static Error restoreStatOnFile(StringRef Filename, const sys::fs::file_status &Stat, bool PreserveDates) { diff --git a/llvm/unittests/CMakeLists.txt b/llvm/unittests/CMakeLists.txt --- a/llvm/unittests/CMakeLists.txt +++ b/llvm/unittests/CMakeLists.txt @@ -35,6 +35,7 @@ add_subdirectory(MI) add_subdirectory(Object) add_subdirectory(ObjectYAML) +add_subdirectory(ObjCopy) add_subdirectory(Option) add_subdirectory(Remarks) add_subdirectory(Passes) diff --git a/llvm/unittests/ObjCopy/CMakeLists.txt b/llvm/unittests/ObjCopy/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/llvm/unittests/ObjCopy/CMakeLists.txt @@ -0,0 +1,11 @@ +set(LLVM_LINK_COMPONENTS + Object + ObjCopy + ObjectYAML + ) + +add_llvm_unittest(ObjCopyTests + ObjCopyTest.cpp + ) + +target_link_libraries(ObjCopyTests PRIVATE LLVMTestingSupport) diff --git a/llvm/unittests/ObjCopy/ObjCopyTest.cpp b/llvm/unittests/ObjCopy/ObjCopyTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/ObjCopy/ObjCopyTest.cpp @@ -0,0 +1,120 @@ +//===- 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/ObjCopy/ObjCopy.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ObjCopy/Buffer.h" +#include "llvm/ObjCopy/COFF/COFFObjcopy.h" +#include "llvm/ObjCopy/CopyConfig.h" +#include "llvm/ObjCopy/ELF/ELFObjcopy.h" +#include "llvm/ObjCopy/MachO/MachOObjcopy.h" +#include "llvm/ObjCopy/wasm/WasmObjcopy.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Wasm.h" +#include "llvm/ObjectYAML/yaml2obj.h" +#include "llvm/Support/Error.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 IsValidFormat) { + auto ErrHandler = [&](const Twine &Msg) { FAIL() << "Error: " << Msg; }; + + // Create Object file from yaml description. + SmallString<0> Storage; + std::unique_ptr Obj = + yaml2ObjectFile(Storage, YamlCreationString, ErrHandler); + ASSERT_TRUE(Obj); + ASSERT_TRUE(IsValidFormat(*Obj)); + + CopyConfig Config; + Config.OutputFilename = "a.out"; + + // Call executeObjcopyOnBinary() from ObjCopy library. + objcopy::MemBuffer FB(Config.OutputFilename); + Error Err = objcopy::executeObjcopyOnBinary(Config, *Obj.get(), FB); + ASSERT_FALSE(std::move(Err)); + + // Load and check copied file. + std::unique_ptr WFB = FB.releaseMemoryBuffer(); + Expected> Result = + ObjectFile::createObjectFile(WFB->getMemBufferRef()); + ASSERT_THAT_EXPECTED(Result, Succeeded()); + ASSERT_TRUE(IsValidFormat(**Result)); +} + +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 +... +# CHECK: --- !WASM +# CHECK: FileHeader: +# CHECK: Version: 0x00000001 +# CHECK: ... +)", + [](const Binary &File) { return File.isWasm(); }); +}