xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===- ObjcopyOptions.cpp -------------------------------------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "ObjcopyOptions.h"
1081ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h"
1106c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
1281ad6265SDimitry Andric #include "llvm/ADT/StringRef.h"
13*0fca6ea1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
1481ad6265SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
1581ad6265SDimitry Andric #include "llvm/ObjCopy/CommonConfig.h"
1681ad6265SDimitry Andric #include "llvm/ObjCopy/ConfigManager.h"
1781ad6265SDimitry Andric #include "llvm/ObjCopy/MachO/MachOConfig.h"
18*0fca6ea1SDimitry Andric #include "llvm/Object/Binary.h"
1981ad6265SDimitry Andric #include "llvm/Option/Arg.h"
2081ad6265SDimitry Andric #include "llvm/Option/ArgList.h"
2181ad6265SDimitry Andric #include "llvm/Support/CRC.h"
2281ad6265SDimitry Andric #include "llvm/Support/CommandLine.h"
2381ad6265SDimitry Andric #include "llvm/Support/Compression.h"
2481ad6265SDimitry Andric #include "llvm/Support/Errc.h"
2581ad6265SDimitry Andric #include "llvm/Support/Error.h"
2681ad6265SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
2781ad6265SDimitry Andric 
2881ad6265SDimitry Andric using namespace llvm;
2981ad6265SDimitry Andric using namespace llvm::objcopy;
30*0fca6ea1SDimitry Andric using namespace llvm::object;
315f757f3fSDimitry Andric using namespace llvm::opt;
3281ad6265SDimitry Andric 
3381ad6265SDimitry Andric namespace {
3481ad6265SDimitry Andric enum ObjcopyID {
3581ad6265SDimitry Andric   OBJCOPY_INVALID = 0, // This is not an option ID.
365f757f3fSDimitry Andric #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
3781ad6265SDimitry Andric #include "ObjcopyOpts.inc"
3881ad6265SDimitry Andric #undef OPTION
3981ad6265SDimitry Andric };
4081ad6265SDimitry Andric 
41bdd1243dSDimitry Andric namespace objcopy_opt {
42bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE)                                                    \
43bdd1243dSDimitry Andric   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
44bdd1243dSDimitry Andric   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
45bdd1243dSDimitry Andric                                                 std::size(NAME##_init) - 1);
4681ad6265SDimitry Andric #include "ObjcopyOpts.inc"
4781ad6265SDimitry Andric #undef PREFIX
4881ad6265SDimitry Andric 
49bdd1243dSDimitry Andric static constexpr opt::OptTable::Info ObjcopyInfoTable[] = {
505f757f3fSDimitry Andric #define OPTION(...)                                                            \
515f757f3fSDimitry Andric   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
5281ad6265SDimitry Andric #include "ObjcopyOpts.inc"
5381ad6265SDimitry Andric #undef OPTION
5481ad6265SDimitry Andric };
55bdd1243dSDimitry Andric } // namespace objcopy_opt
5681ad6265SDimitry Andric 
57bdd1243dSDimitry Andric class ObjcopyOptTable : public opt::GenericOptTable {
5881ad6265SDimitry Andric public:
59bdd1243dSDimitry Andric   ObjcopyOptTable() : opt::GenericOptTable(objcopy_opt::ObjcopyInfoTable) {
6081ad6265SDimitry Andric     setGroupedShortOptions(true);
6181ad6265SDimitry Andric   }
6281ad6265SDimitry Andric };
6381ad6265SDimitry Andric 
6481ad6265SDimitry Andric enum InstallNameToolID {
6581ad6265SDimitry Andric   INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
665f757f3fSDimitry Andric #define OPTION(...)                                                            \
675f757f3fSDimitry Andric   LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
6881ad6265SDimitry Andric #include "InstallNameToolOpts.inc"
6981ad6265SDimitry Andric #undef OPTION
7081ad6265SDimitry Andric };
7181ad6265SDimitry Andric 
72bdd1243dSDimitry Andric namespace install_name_tool {
73bdd1243dSDimitry Andric 
7481ad6265SDimitry Andric #define PREFIX(NAME, VALUE)                                                    \
75bdd1243dSDimitry Andric   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
76bdd1243dSDimitry Andric   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
77bdd1243dSDimitry Andric                                                 std::size(NAME##_init) - 1);
7881ad6265SDimitry Andric #include "InstallNameToolOpts.inc"
7981ad6265SDimitry Andric #undef PREFIX
8081ad6265SDimitry Andric 
81bdd1243dSDimitry Andric static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = {
825f757f3fSDimitry Andric #define OPTION(...)                                                            \
835f757f3fSDimitry Andric   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
8481ad6265SDimitry Andric #include "InstallNameToolOpts.inc"
8581ad6265SDimitry Andric #undef OPTION
8681ad6265SDimitry Andric };
87bdd1243dSDimitry Andric } // namespace install_name_tool
8881ad6265SDimitry Andric 
89bdd1243dSDimitry Andric class InstallNameToolOptTable : public opt::GenericOptTable {
9081ad6265SDimitry Andric public:
91bdd1243dSDimitry Andric   InstallNameToolOptTable()
92bdd1243dSDimitry Andric       : GenericOptTable(install_name_tool::InstallNameToolInfoTable) {}
9381ad6265SDimitry Andric };
9481ad6265SDimitry Andric 
9581ad6265SDimitry Andric enum BitcodeStripID {
9681ad6265SDimitry Andric   BITCODE_STRIP_INVALID = 0, // This is not an option ID.
975f757f3fSDimitry Andric #define OPTION(...)                                                            \
985f757f3fSDimitry Andric   LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
9981ad6265SDimitry Andric #include "BitcodeStripOpts.inc"
10081ad6265SDimitry Andric #undef OPTION
10181ad6265SDimitry Andric };
10281ad6265SDimitry Andric 
103bdd1243dSDimitry Andric namespace bitcode_strip {
104bdd1243dSDimitry Andric 
105bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE)                                                    \
106bdd1243dSDimitry Andric   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
107bdd1243dSDimitry Andric   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
108bdd1243dSDimitry Andric                                                 std::size(NAME##_init) - 1);
10981ad6265SDimitry Andric #include "BitcodeStripOpts.inc"
11081ad6265SDimitry Andric #undef PREFIX
11181ad6265SDimitry Andric 
112bdd1243dSDimitry Andric static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = {
1135f757f3fSDimitry Andric #define OPTION(...)                                                            \
1145f757f3fSDimitry Andric   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
11581ad6265SDimitry Andric #include "BitcodeStripOpts.inc"
11681ad6265SDimitry Andric #undef OPTION
11781ad6265SDimitry Andric };
118bdd1243dSDimitry Andric } // namespace bitcode_strip
11981ad6265SDimitry Andric 
120bdd1243dSDimitry Andric class BitcodeStripOptTable : public opt::GenericOptTable {
12181ad6265SDimitry Andric public:
122bdd1243dSDimitry Andric   BitcodeStripOptTable()
123bdd1243dSDimitry Andric       : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable) {}
12481ad6265SDimitry Andric };
12581ad6265SDimitry Andric 
12681ad6265SDimitry Andric enum StripID {
12781ad6265SDimitry Andric   STRIP_INVALID = 0, // This is not an option ID.
1285f757f3fSDimitry Andric #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
12981ad6265SDimitry Andric #include "StripOpts.inc"
13081ad6265SDimitry Andric #undef OPTION
13181ad6265SDimitry Andric };
13281ad6265SDimitry Andric 
133bdd1243dSDimitry Andric namespace strip {
134bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE)                                                    \
135bdd1243dSDimitry Andric   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
136bdd1243dSDimitry Andric   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
137bdd1243dSDimitry Andric                                                 std::size(NAME##_init) - 1);
13881ad6265SDimitry Andric #include "StripOpts.inc"
13981ad6265SDimitry Andric #undef PREFIX
14081ad6265SDimitry Andric 
141bdd1243dSDimitry Andric static constexpr opt::OptTable::Info StripInfoTable[] = {
1425f757f3fSDimitry Andric #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
14381ad6265SDimitry Andric #include "StripOpts.inc"
14481ad6265SDimitry Andric #undef OPTION
14581ad6265SDimitry Andric };
146bdd1243dSDimitry Andric } // namespace strip
14781ad6265SDimitry Andric 
148bdd1243dSDimitry Andric class StripOptTable : public opt::GenericOptTable {
14981ad6265SDimitry Andric public:
150bdd1243dSDimitry Andric   StripOptTable() : GenericOptTable(strip::StripInfoTable) {
151bdd1243dSDimitry Andric     setGroupedShortOptions(true);
152bdd1243dSDimitry Andric   }
15381ad6265SDimitry Andric };
15481ad6265SDimitry Andric 
15581ad6265SDimitry Andric } // namespace
15681ad6265SDimitry Andric 
15781ad6265SDimitry Andric static SectionFlag parseSectionRenameFlag(StringRef SectionName) {
15881ad6265SDimitry Andric   return llvm::StringSwitch<SectionFlag>(SectionName)
15981ad6265SDimitry Andric       .CaseLower("alloc", SectionFlag::SecAlloc)
16081ad6265SDimitry Andric       .CaseLower("load", SectionFlag::SecLoad)
16181ad6265SDimitry Andric       .CaseLower("noload", SectionFlag::SecNoload)
16281ad6265SDimitry Andric       .CaseLower("readonly", SectionFlag::SecReadonly)
16381ad6265SDimitry Andric       .CaseLower("debug", SectionFlag::SecDebug)
16481ad6265SDimitry Andric       .CaseLower("code", SectionFlag::SecCode)
16581ad6265SDimitry Andric       .CaseLower("data", SectionFlag::SecData)
16681ad6265SDimitry Andric       .CaseLower("rom", SectionFlag::SecRom)
16781ad6265SDimitry Andric       .CaseLower("merge", SectionFlag::SecMerge)
16881ad6265SDimitry Andric       .CaseLower("strings", SectionFlag::SecStrings)
16981ad6265SDimitry Andric       .CaseLower("contents", SectionFlag::SecContents)
17081ad6265SDimitry Andric       .CaseLower("share", SectionFlag::SecShare)
17181ad6265SDimitry Andric       .CaseLower("exclude", SectionFlag::SecExclude)
1725f757f3fSDimitry Andric       .CaseLower("large", SectionFlag::SecLarge)
17381ad6265SDimitry Andric       .Default(SectionFlag::SecNone);
17481ad6265SDimitry Andric }
17581ad6265SDimitry Andric 
17681ad6265SDimitry Andric static Expected<SectionFlag>
17781ad6265SDimitry Andric parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
17881ad6265SDimitry Andric   SectionFlag ParsedFlags = SectionFlag::SecNone;
17981ad6265SDimitry Andric   for (StringRef Flag : SectionFlags) {
18081ad6265SDimitry Andric     SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
18181ad6265SDimitry Andric     if (ParsedFlag == SectionFlag::SecNone)
18281ad6265SDimitry Andric       return createStringError(
18381ad6265SDimitry Andric           errc::invalid_argument,
18481ad6265SDimitry Andric           "unrecognized section flag '%s'. Flags supported for GNU "
18581ad6265SDimitry Andric           "compatibility: alloc, load, noload, readonly, exclude, debug, "
1865f757f3fSDimitry Andric           "code, data, rom, share, contents, merge, strings, large",
18781ad6265SDimitry Andric           Flag.str().c_str());
18881ad6265SDimitry Andric     ParsedFlags |= ParsedFlag;
18981ad6265SDimitry Andric   }
19081ad6265SDimitry Andric 
19181ad6265SDimitry Andric   return ParsedFlags;
19281ad6265SDimitry Andric }
19381ad6265SDimitry Andric 
19481ad6265SDimitry Andric static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {
19581ad6265SDimitry Andric   if (!FlagValue.contains('='))
19681ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
19781ad6265SDimitry Andric                              "bad format for --rename-section: missing '='");
19881ad6265SDimitry Andric 
19981ad6265SDimitry Andric   // Initial split: ".foo" = ".bar,f1,f2,..."
20081ad6265SDimitry Andric   auto Old2New = FlagValue.split('=');
20181ad6265SDimitry Andric   SectionRename SR;
20281ad6265SDimitry Andric   SR.OriginalName = Old2New.first;
20381ad6265SDimitry Andric 
20481ad6265SDimitry Andric   // Flags split: ".bar" "f1" "f2" ...
20581ad6265SDimitry Andric   SmallVector<StringRef, 6> NameAndFlags;
20681ad6265SDimitry Andric   Old2New.second.split(NameAndFlags, ',');
20781ad6265SDimitry Andric   SR.NewName = NameAndFlags[0];
20881ad6265SDimitry Andric 
20981ad6265SDimitry Andric   if (NameAndFlags.size() > 1) {
21081ad6265SDimitry Andric     Expected<SectionFlag> ParsedFlagSet =
211bdd1243dSDimitry Andric         parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front());
21281ad6265SDimitry Andric     if (!ParsedFlagSet)
21381ad6265SDimitry Andric       return ParsedFlagSet.takeError();
21481ad6265SDimitry Andric     SR.NewFlags = *ParsedFlagSet;
21581ad6265SDimitry Andric   }
21681ad6265SDimitry Andric 
21781ad6265SDimitry Andric   return SR;
21881ad6265SDimitry Andric }
21981ad6265SDimitry Andric 
22081ad6265SDimitry Andric static Expected<std::pair<StringRef, uint64_t>>
221753f127fSDimitry Andric parseSetSectionAttribute(StringRef Option, StringRef FlagValue) {
22281ad6265SDimitry Andric   if (!FlagValue.contains('='))
223753f127fSDimitry Andric     return make_error<StringError>("bad format for " + Option + ": missing '='",
224753f127fSDimitry Andric                                    errc::invalid_argument);
22581ad6265SDimitry Andric   auto Split = StringRef(FlagValue).split('=');
22681ad6265SDimitry Andric   if (Split.first.empty())
227753f127fSDimitry Andric     return make_error<StringError>("bad format for " + Option +
228753f127fSDimitry Andric                                        ": missing section name",
229753f127fSDimitry Andric                                    errc::invalid_argument);
230753f127fSDimitry Andric   uint64_t Value;
231753f127fSDimitry Andric   if (Split.second.getAsInteger(0, Value))
232753f127fSDimitry Andric     return make_error<StringError>("invalid value for " + Option + ": '" +
233753f127fSDimitry Andric                                        Split.second + "'",
234753f127fSDimitry Andric                                    errc::invalid_argument);
235753f127fSDimitry Andric   return std::make_pair(Split.first, Value);
23681ad6265SDimitry Andric }
23781ad6265SDimitry Andric 
23881ad6265SDimitry Andric static Expected<SectionFlagsUpdate>
23981ad6265SDimitry Andric parseSetSectionFlagValue(StringRef FlagValue) {
24081ad6265SDimitry Andric   if (!StringRef(FlagValue).contains('='))
24181ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
24281ad6265SDimitry Andric                              "bad format for --set-section-flags: missing '='");
24381ad6265SDimitry Andric 
24481ad6265SDimitry Andric   // Initial split: ".foo" = "f1,f2,..."
24581ad6265SDimitry Andric   auto Section2Flags = StringRef(FlagValue).split('=');
24681ad6265SDimitry Andric   SectionFlagsUpdate SFU;
24781ad6265SDimitry Andric   SFU.Name = Section2Flags.first;
24881ad6265SDimitry Andric 
24981ad6265SDimitry Andric   // Flags split: "f1" "f2" ...
25081ad6265SDimitry Andric   SmallVector<StringRef, 6> SectionFlags;
25181ad6265SDimitry Andric   Section2Flags.second.split(SectionFlags, ',');
25281ad6265SDimitry Andric   Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags);
25381ad6265SDimitry Andric   if (!ParsedFlagSet)
25481ad6265SDimitry Andric     return ParsedFlagSet.takeError();
25581ad6265SDimitry Andric   SFU.NewFlags = *ParsedFlagSet;
25681ad6265SDimitry Andric 
25781ad6265SDimitry Andric   return SFU;
25881ad6265SDimitry Andric }
25981ad6265SDimitry Andric 
260*0fca6ea1SDimitry Andric static Expected<uint8_t> parseVisibilityType(StringRef VisType) {
261*0fca6ea1SDimitry Andric   const uint8_t Invalid = 0xff;
262*0fca6ea1SDimitry Andric   uint8_t type = StringSwitch<uint8_t>(VisType)
263*0fca6ea1SDimitry Andric                      .Case("default", ELF::STV_DEFAULT)
264*0fca6ea1SDimitry Andric                      .Case("hidden", ELF::STV_HIDDEN)
265*0fca6ea1SDimitry Andric                      .Case("internal", ELF::STV_INTERNAL)
266*0fca6ea1SDimitry Andric                      .Case("protected", ELF::STV_PROTECTED)
267*0fca6ea1SDimitry Andric                      .Default(Invalid);
268*0fca6ea1SDimitry Andric   if (type == Invalid)
269*0fca6ea1SDimitry Andric     return createStringError(errc::invalid_argument,
270*0fca6ea1SDimitry Andric                              "'%s' is not a valid symbol visibility",
271*0fca6ea1SDimitry Andric                              VisType.str().c_str());
272*0fca6ea1SDimitry Andric   return type;
273*0fca6ea1SDimitry Andric }
274*0fca6ea1SDimitry Andric 
27581ad6265SDimitry Andric namespace {
27681ad6265SDimitry Andric struct TargetInfo {
27781ad6265SDimitry Andric   FileFormat Format;
27881ad6265SDimitry Andric   MachineInfo Machine;
27981ad6265SDimitry Andric };
28081ad6265SDimitry Andric } // namespace
28181ad6265SDimitry Andric 
28281ad6265SDimitry Andric // FIXME: consolidate with the bfd parsing used by lld.
28381ad6265SDimitry Andric static const StringMap<MachineInfo> TargetMap{
28481ad6265SDimitry Andric     // Name, {EMachine, 64bit, LittleEndian}
28581ad6265SDimitry Andric     // x86
28681ad6265SDimitry Andric     {"elf32-i386", {ELF::EM_386, false, true}},
28781ad6265SDimitry Andric     {"elf32-x86-64", {ELF::EM_X86_64, false, true}},
28881ad6265SDimitry Andric     {"elf64-x86-64", {ELF::EM_X86_64, true, true}},
28981ad6265SDimitry Andric     // Intel MCU
29081ad6265SDimitry Andric     {"elf32-iamcu", {ELF::EM_IAMCU, false, true}},
29181ad6265SDimitry Andric     // ARM
29281ad6265SDimitry Andric     {"elf32-littlearm", {ELF::EM_ARM, false, true}},
29381ad6265SDimitry Andric     // ARM AArch64
29481ad6265SDimitry Andric     {"elf64-aarch64", {ELF::EM_AARCH64, true, true}},
29581ad6265SDimitry Andric     {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}},
29681ad6265SDimitry Andric     // RISC-V
29781ad6265SDimitry Andric     {"elf32-littleriscv", {ELF::EM_RISCV, false, true}},
29881ad6265SDimitry Andric     {"elf64-littleriscv", {ELF::EM_RISCV, true, true}},
29981ad6265SDimitry Andric     // PowerPC
30081ad6265SDimitry Andric     {"elf32-powerpc", {ELF::EM_PPC, false, false}},
30181ad6265SDimitry Andric     {"elf32-powerpcle", {ELF::EM_PPC, false, true}},
30281ad6265SDimitry Andric     {"elf64-powerpc", {ELF::EM_PPC64, true, false}},
30381ad6265SDimitry Andric     {"elf64-powerpcle", {ELF::EM_PPC64, true, true}},
30481ad6265SDimitry Andric     // MIPS
30581ad6265SDimitry Andric     {"elf32-bigmips", {ELF::EM_MIPS, false, false}},
30681ad6265SDimitry Andric     {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}},
30781ad6265SDimitry Andric     {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}},
30881ad6265SDimitry Andric     {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}},
30981ad6265SDimitry Andric     {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}},
31081ad6265SDimitry Andric     {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}},
31181ad6265SDimitry Andric     {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}},
31281ad6265SDimitry Andric     // SPARC
31381ad6265SDimitry Andric     {"elf32-sparc", {ELF::EM_SPARC, false, false}},
31481ad6265SDimitry Andric     {"elf32-sparcel", {ELF::EM_SPARC, false, true}},
31506c3fb27SDimitry Andric     // Hexagon
31681ad6265SDimitry Andric     {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}},
31706c3fb27SDimitry Andric     // LoongArch
31806c3fb27SDimitry Andric     {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}},
31906c3fb27SDimitry Andric     {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}},
32056727255SDimitry Andric     // SystemZ
32156727255SDimitry Andric     {"elf64-s390", {ELF::EM_S390, true, false}},
32281ad6265SDimitry Andric };
32381ad6265SDimitry Andric 
32481ad6265SDimitry Andric static Expected<TargetInfo>
32581ad6265SDimitry Andric getOutputTargetInfoByTargetName(StringRef TargetName) {
32681ad6265SDimitry Andric   StringRef OriginalTargetName = TargetName;
32781ad6265SDimitry Andric   bool IsFreeBSD = TargetName.consume_back("-freebsd");
32881ad6265SDimitry Andric   auto Iter = TargetMap.find(TargetName);
32981ad6265SDimitry Andric   if (Iter == std::end(TargetMap))
33081ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
33181ad6265SDimitry Andric                              "invalid output format: '%s'",
33281ad6265SDimitry Andric                              OriginalTargetName.str().c_str());
33381ad6265SDimitry Andric   MachineInfo MI = Iter->getValue();
33481ad6265SDimitry Andric   if (IsFreeBSD)
33581ad6265SDimitry Andric     MI.OSABI = ELF::ELFOSABI_FREEBSD;
33681ad6265SDimitry Andric 
33781ad6265SDimitry Andric   FileFormat Format;
3385f757f3fSDimitry Andric   if (TargetName.starts_with("elf"))
33981ad6265SDimitry Andric     Format = FileFormat::ELF;
34081ad6265SDimitry Andric   else
34181ad6265SDimitry Andric     // This should never happen because `TargetName` is valid (it certainly
34281ad6265SDimitry Andric     // exists in the TargetMap).
34381ad6265SDimitry Andric     llvm_unreachable("unknown target prefix");
34481ad6265SDimitry Andric 
34581ad6265SDimitry Andric   return {TargetInfo{Format, MI}};
34681ad6265SDimitry Andric }
34781ad6265SDimitry Andric 
34881ad6265SDimitry Andric static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
34981ad6265SDimitry Andric                                 StringRef Filename, MatchStyle MS,
35081ad6265SDimitry Andric                                 function_ref<Error(Error)> ErrorCallback) {
35181ad6265SDimitry Andric   StringSaver Saver(Alloc);
35281ad6265SDimitry Andric   SmallVector<StringRef, 16> Lines;
35381ad6265SDimitry Andric   auto BufOrErr = MemoryBuffer::getFile(Filename);
35481ad6265SDimitry Andric   if (!BufOrErr)
35581ad6265SDimitry Andric     return createFileError(Filename, BufOrErr.getError());
35681ad6265SDimitry Andric 
35781ad6265SDimitry Andric   BufOrErr.get()->getBuffer().split(Lines, '\n');
35881ad6265SDimitry Andric   for (StringRef Line : Lines) {
35981ad6265SDimitry Andric     // Ignore everything after '#', trim whitespace, and only add the symbol if
36081ad6265SDimitry Andric     // it's not empty.
36181ad6265SDimitry Andric     auto TrimmedLine = Line.split('#').first.trim();
36281ad6265SDimitry Andric     if (!TrimmedLine.empty())
36381ad6265SDimitry Andric       if (Error E = Symbols.addMatcher(NameOrPattern::create(
36481ad6265SDimitry Andric               Saver.save(TrimmedLine), MS, ErrorCallback)))
36581ad6265SDimitry Andric         return E;
36681ad6265SDimitry Andric   }
36781ad6265SDimitry Andric 
36881ad6265SDimitry Andric   return Error::success();
36981ad6265SDimitry Andric }
37081ad6265SDimitry Andric 
37181ad6265SDimitry Andric static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
37281ad6265SDimitry Andric                                         BumpPtrAllocator &Alloc,
37381ad6265SDimitry Andric                                         StringRef Filename) {
37481ad6265SDimitry Andric   StringSaver Saver(Alloc);
37581ad6265SDimitry Andric   SmallVector<StringRef, 16> Lines;
37681ad6265SDimitry Andric   auto BufOrErr = MemoryBuffer::getFile(Filename);
37781ad6265SDimitry Andric   if (!BufOrErr)
37881ad6265SDimitry Andric     return createFileError(Filename, BufOrErr.getError());
37981ad6265SDimitry Andric 
38081ad6265SDimitry Andric   BufOrErr.get()->getBuffer().split(Lines, '\n');
38181ad6265SDimitry Andric   size_t NumLines = Lines.size();
38281ad6265SDimitry Andric   for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) {
38381ad6265SDimitry Andric     StringRef TrimmedLine = Lines[LineNo].split('#').first.trim();
38481ad6265SDimitry Andric     if (TrimmedLine.empty())
38581ad6265SDimitry Andric       continue;
38681ad6265SDimitry Andric 
38781ad6265SDimitry Andric     std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' ');
38881ad6265SDimitry Andric     StringRef NewName = Pair.second.trim();
38981ad6265SDimitry Andric     if (NewName.empty())
39081ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
39181ad6265SDimitry Andric                                "%s:%zu: missing new symbol name",
39281ad6265SDimitry Andric                                Filename.str().c_str(), LineNo + 1);
39381ad6265SDimitry Andric     SymbolsToRename.insert({Pair.first, NewName});
39481ad6265SDimitry Andric   }
39581ad6265SDimitry Andric   return Error::success();
39681ad6265SDimitry Andric }
39781ad6265SDimitry Andric 
39881ad6265SDimitry Andric template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
39981ad6265SDimitry Andric   T Result;
40081ad6265SDimitry Andric   if (Val.getAsInteger(0, Result))
40181ad6265SDimitry Andric     return errc::invalid_argument;
40281ad6265SDimitry Andric   return Result;
40381ad6265SDimitry Andric }
40481ad6265SDimitry Andric 
40581ad6265SDimitry Andric namespace {
40681ad6265SDimitry Andric 
40781ad6265SDimitry Andric enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip };
40881ad6265SDimitry Andric 
40981ad6265SDimitry Andric } // anonymous namespace
41081ad6265SDimitry Andric 
41181ad6265SDimitry Andric static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
41281ad6265SDimitry Andric                       ToolType Tool) {
41381ad6265SDimitry Andric   StringRef HelpText, ToolName;
41481ad6265SDimitry Andric   switch (Tool) {
41581ad6265SDimitry Andric   case ToolType::Objcopy:
41681ad6265SDimitry Andric     ToolName = "llvm-objcopy";
41781ad6265SDimitry Andric     HelpText = " [options] input [output]";
41881ad6265SDimitry Andric     break;
41981ad6265SDimitry Andric   case ToolType::Strip:
42081ad6265SDimitry Andric     ToolName = "llvm-strip";
42181ad6265SDimitry Andric     HelpText = " [options] inputs...";
42281ad6265SDimitry Andric     break;
42381ad6265SDimitry Andric   case ToolType::InstallNameTool:
42481ad6265SDimitry Andric     ToolName = "llvm-install-name-tool";
42581ad6265SDimitry Andric     HelpText = " [options] input";
42681ad6265SDimitry Andric     break;
42781ad6265SDimitry Andric   case ToolType::BitcodeStrip:
42881ad6265SDimitry Andric     ToolName = "llvm-bitcode-strip";
42981ad6265SDimitry Andric     HelpText = " [options] input";
43081ad6265SDimitry Andric     break;
43181ad6265SDimitry Andric   }
43281ad6265SDimitry Andric   OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
43381ad6265SDimitry Andric                      (ToolName + " tool").str().c_str());
43481ad6265SDimitry Andric   // TODO: Replace this with libOption call once it adds extrahelp support.
43581ad6265SDimitry Andric   // The CommandLine library has a cl::extrahelp class to support this,
43681ad6265SDimitry Andric   // but libOption does not have that yet.
43781ad6265SDimitry Andric   OS << "\nPass @FILE as argument to read options from FILE.\n";
43881ad6265SDimitry Andric }
43981ad6265SDimitry Andric 
44081ad6265SDimitry Andric static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
44181ad6265SDimitry Andric   // Parse value given with --add-symbol option and create the
44281ad6265SDimitry Andric   // new symbol if possible. The value format for --add-symbol is:
44381ad6265SDimitry Andric   //
44481ad6265SDimitry Andric   // <name>=[<section>:]<value>[,<flags>]
44581ad6265SDimitry Andric   //
44681ad6265SDimitry Andric   // where:
44781ad6265SDimitry Andric   // <name> - symbol name, can be empty string
44881ad6265SDimitry Andric   // <section> - optional section name. If not given ABS symbol is created
44981ad6265SDimitry Andric   // <value> - symbol value, can be decimal or hexadecimal number prefixed
45081ad6265SDimitry Andric   //           with 0x.
45181ad6265SDimitry Andric   // <flags> - optional flags affecting symbol type, binding or visibility.
45281ad6265SDimitry Andric   NewSymbolInfo SI;
45381ad6265SDimitry Andric   StringRef Value;
45481ad6265SDimitry Andric   std::tie(SI.SymbolName, Value) = FlagValue.split('=');
45581ad6265SDimitry Andric   if (Value.empty())
45681ad6265SDimitry Andric     return createStringError(
45781ad6265SDimitry Andric         errc::invalid_argument,
45881ad6265SDimitry Andric         "bad format for --add-symbol, missing '=' after '%s'",
45981ad6265SDimitry Andric         SI.SymbolName.str().c_str());
46081ad6265SDimitry Andric 
46181ad6265SDimitry Andric   if (Value.contains(':')) {
46281ad6265SDimitry Andric     std::tie(SI.SectionName, Value) = Value.split(':');
46381ad6265SDimitry Andric     if (SI.SectionName.empty() || Value.empty())
46481ad6265SDimitry Andric       return createStringError(
46581ad6265SDimitry Andric           errc::invalid_argument,
46681ad6265SDimitry Andric           "bad format for --add-symbol, missing section name or symbol value");
46781ad6265SDimitry Andric   }
46881ad6265SDimitry Andric 
46981ad6265SDimitry Andric   SmallVector<StringRef, 6> Flags;
47081ad6265SDimitry Andric   Value.split(Flags, ',');
47181ad6265SDimitry Andric   if (Flags[0].getAsInteger(0, SI.Value))
47281ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
47381ad6265SDimitry Andric                              Flags[0].str().c_str());
47481ad6265SDimitry Andric 
47581ad6265SDimitry Andric   using Functor = std::function<void()>;
47681ad6265SDimitry Andric   SmallVector<StringRef, 6> UnsupportedFlags;
47781ad6265SDimitry Andric   for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
47881ad6265SDimitry Andric     static_cast<Functor>(
47981ad6265SDimitry Andric         StringSwitch<Functor>(Flags[I])
48081ad6265SDimitry Andric             .CaseLower("global",
48181ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Global); })
48281ad6265SDimitry Andric             .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); })
48381ad6265SDimitry Andric             .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); })
48481ad6265SDimitry Andric             .CaseLower("default",
48581ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Default); })
48681ad6265SDimitry Andric             .CaseLower("hidden",
48781ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Hidden); })
48881ad6265SDimitry Andric             .CaseLower("protected",
48981ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Protected); })
49081ad6265SDimitry Andric             .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); })
49181ad6265SDimitry Andric             .CaseLower("section",
49281ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Section); })
49381ad6265SDimitry Andric             .CaseLower("object",
49481ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Object); })
49581ad6265SDimitry Andric             .CaseLower("function",
49681ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Function); })
49781ad6265SDimitry Andric             .CaseLower(
49881ad6265SDimitry Andric                 "indirect-function",
49981ad6265SDimitry Andric                 [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); })
50081ad6265SDimitry Andric             .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); })
50181ad6265SDimitry Andric             .CaseLower("constructor",
50281ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Constructor); })
50381ad6265SDimitry Andric             .CaseLower("warning",
50481ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Warning); })
50581ad6265SDimitry Andric             .CaseLower("indirect",
50681ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Indirect); })
50781ad6265SDimitry Andric             .CaseLower("synthetic",
50881ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::Synthetic); })
50981ad6265SDimitry Andric             .CaseLower("unique-object",
51081ad6265SDimitry Andric                        [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); })
51181ad6265SDimitry Andric             .StartsWithLower("before=",
51281ad6265SDimitry Andric                              [&] {
51381ad6265SDimitry Andric                                StringRef SymNamePart =
51481ad6265SDimitry Andric                                    Flags[I].split('=').second;
51581ad6265SDimitry Andric 
51681ad6265SDimitry Andric                                if (!SymNamePart.empty())
51781ad6265SDimitry Andric                                  SI.BeforeSyms.push_back(SymNamePart);
51881ad6265SDimitry Andric                              })
51981ad6265SDimitry Andric             .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
52081ad6265SDimitry Andric   if (!UnsupportedFlags.empty())
52181ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
52281ad6265SDimitry Andric                              "unsupported flag%s for --add-symbol: '%s'",
52381ad6265SDimitry Andric                              UnsupportedFlags.size() > 1 ? "s" : "",
52481ad6265SDimitry Andric                              join(UnsupportedFlags, "', '").c_str());
52581ad6265SDimitry Andric 
52681ad6265SDimitry Andric   return SI;
52781ad6265SDimitry Andric }
52881ad6265SDimitry Andric 
52981ad6265SDimitry Andric // Parse input option \p ArgValue and load section data. This function
53081ad6265SDimitry Andric // extracts section name and name of the file keeping section data from
53181ad6265SDimitry Andric // ArgValue, loads data from the file, and stores section name and data
53281ad6265SDimitry Andric // into the vector of new sections \p NewSections.
53381ad6265SDimitry Andric static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
534*0fca6ea1SDimitry Andric                                 SmallVector<NewSectionInfo, 0> &NewSections) {
53581ad6265SDimitry Andric   if (!ArgValue.contains('='))
53681ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
53781ad6265SDimitry Andric                              "bad format for " + OptionName + ": missing '='");
53881ad6265SDimitry Andric 
53981ad6265SDimitry Andric   std::pair<StringRef, StringRef> SecPair = ArgValue.split("=");
54081ad6265SDimitry Andric   if (SecPair.second.empty())
54181ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "bad format for " +
54281ad6265SDimitry Andric                                                          OptionName +
54381ad6265SDimitry Andric                                                          ": missing file name");
54481ad6265SDimitry Andric 
54581ad6265SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
54681ad6265SDimitry Andric       MemoryBuffer::getFile(SecPair.second);
54781ad6265SDimitry Andric   if (!BufOrErr)
54881ad6265SDimitry Andric     return createFileError(SecPair.second,
54981ad6265SDimitry Andric                            errorCodeToError(BufOrErr.getError()));
55081ad6265SDimitry Andric 
55181ad6265SDimitry Andric   NewSections.push_back({SecPair.first, std::move(*BufOrErr)});
55281ad6265SDimitry Andric   return Error::success();
55381ad6265SDimitry Andric }
55481ad6265SDimitry Andric 
555*0fca6ea1SDimitry Andric static Expected<int64_t> parseChangeSectionLMA(StringRef ArgValue,
556*0fca6ea1SDimitry Andric                                                StringRef OptionName) {
557*0fca6ea1SDimitry Andric   StringRef StringValue;
558*0fca6ea1SDimitry Andric   if (ArgValue.starts_with("*+")) {
559*0fca6ea1SDimitry Andric     StringValue = ArgValue.slice(2, StringRef::npos);
560*0fca6ea1SDimitry Andric   } else if (ArgValue.starts_with("*-")) {
561*0fca6ea1SDimitry Andric     StringValue = ArgValue.slice(1, StringRef::npos);
562*0fca6ea1SDimitry Andric   } else if (ArgValue.contains("=")) {
563*0fca6ea1SDimitry Andric     return createStringError(errc::invalid_argument,
564*0fca6ea1SDimitry Andric                              "bad format for " + OptionName +
565*0fca6ea1SDimitry Andric                                  ": changing LMA to a specific value is not "
566*0fca6ea1SDimitry Andric                                  "supported. Use *+val or *-val instead");
567*0fca6ea1SDimitry Andric   } else if (ArgValue.contains("+") || ArgValue.contains("-")) {
568*0fca6ea1SDimitry Andric     return createStringError(errc::invalid_argument,
569*0fca6ea1SDimitry Andric                              "bad format for " + OptionName +
570*0fca6ea1SDimitry Andric                                  ": changing a specific section LMA is not "
571*0fca6ea1SDimitry Andric                                  "supported. Use *+val or *-val instead");
572*0fca6ea1SDimitry Andric   }
573*0fca6ea1SDimitry Andric   if (StringValue.empty())
574*0fca6ea1SDimitry Andric     return createStringError(errc::invalid_argument,
575*0fca6ea1SDimitry Andric                              "bad format for " + OptionName +
576*0fca6ea1SDimitry Andric                                  ": missing LMA offset");
577*0fca6ea1SDimitry Andric 
578*0fca6ea1SDimitry Andric   auto LMAValue = getAsInteger<int64_t>(StringValue);
579*0fca6ea1SDimitry Andric   if (!LMAValue)
580*0fca6ea1SDimitry Andric     return createStringError(LMAValue.getError(),
581*0fca6ea1SDimitry Andric                              "bad format for " + OptionName + ": value after " +
582*0fca6ea1SDimitry Andric                                  ArgValue.slice(0, 2) + " is " + StringValue +
583*0fca6ea1SDimitry Andric                                  " when it should be an integer");
584*0fca6ea1SDimitry Andric   return *LMAValue;
585*0fca6ea1SDimitry Andric }
586*0fca6ea1SDimitry Andric 
58781ad6265SDimitry Andric // parseObjcopyOptions returns the config and sets the input arguments. If a
58881ad6265SDimitry Andric // help flag is set then parseObjcopyOptions will print the help messege and
58981ad6265SDimitry Andric // exit.
59081ad6265SDimitry Andric Expected<DriverConfig>
59181ad6265SDimitry Andric objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
59281ad6265SDimitry Andric                              function_ref<Error(Error)> ErrorCallback) {
59381ad6265SDimitry Andric   DriverConfig DC;
59481ad6265SDimitry Andric   ObjcopyOptTable T;
59581ad6265SDimitry Andric 
59681ad6265SDimitry Andric   const char *const *DashDash =
597bdd1243dSDimitry Andric       llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
598bdd1243dSDimitry Andric   ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
59981ad6265SDimitry Andric   if (DashDash != RawArgsArr.end())
60081ad6265SDimitry Andric     DashDash = std::next(DashDash);
60181ad6265SDimitry Andric 
60281ad6265SDimitry Andric   unsigned MissingArgumentIndex, MissingArgumentCount;
60381ad6265SDimitry Andric   llvm::opt::InputArgList InputArgs =
60481ad6265SDimitry Andric       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
60581ad6265SDimitry Andric 
606*0fca6ea1SDimitry Andric   if (MissingArgumentCount)
607*0fca6ea1SDimitry Andric     return createStringError(
608*0fca6ea1SDimitry Andric         errc::invalid_argument,
609*0fca6ea1SDimitry Andric         "argument to '%s' is missing (expected %d value(s))",
610*0fca6ea1SDimitry Andric         InputArgs.getArgString(MissingArgumentIndex), MissingArgumentCount);
611*0fca6ea1SDimitry Andric 
61281ad6265SDimitry Andric   if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
61381ad6265SDimitry Andric     printHelp(T, errs(), ToolType::Objcopy);
61481ad6265SDimitry Andric     exit(1);
61581ad6265SDimitry Andric   }
61681ad6265SDimitry Andric 
61781ad6265SDimitry Andric   if (InputArgs.hasArg(OBJCOPY_help)) {
61881ad6265SDimitry Andric     printHelp(T, outs(), ToolType::Objcopy);
61981ad6265SDimitry Andric     exit(0);
62081ad6265SDimitry Andric   }
62181ad6265SDimitry Andric 
62281ad6265SDimitry Andric   if (InputArgs.hasArg(OBJCOPY_version)) {
62381ad6265SDimitry Andric     outs() << "llvm-objcopy, compatible with GNU objcopy\n";
62481ad6265SDimitry Andric     cl::PrintVersionMessage();
62581ad6265SDimitry Andric     exit(0);
62681ad6265SDimitry Andric   }
62781ad6265SDimitry Andric 
62881ad6265SDimitry Andric   SmallVector<const char *, 2> Positional;
62981ad6265SDimitry Andric 
630bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
63181ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "unknown argument '%s'",
63281ad6265SDimitry Andric                              Arg->getAsString(InputArgs).c_str());
63381ad6265SDimitry Andric 
634bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
63581ad6265SDimitry Andric     Positional.push_back(Arg->getValue());
63681ad6265SDimitry Andric   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
63781ad6265SDimitry Andric 
63881ad6265SDimitry Andric   if (Positional.empty())
63981ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "no input file specified");
64081ad6265SDimitry Andric 
64181ad6265SDimitry Andric   if (Positional.size() > 2)
64281ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
64381ad6265SDimitry Andric                              "too many positional arguments");
64481ad6265SDimitry Andric 
64581ad6265SDimitry Andric   ConfigManager ConfigMgr;
64681ad6265SDimitry Andric   CommonConfig &Config = ConfigMgr.Common;
64781ad6265SDimitry Andric   COFFConfig &COFFConfig = ConfigMgr.COFF;
64881ad6265SDimitry Andric   ELFConfig &ELFConfig = ConfigMgr.ELF;
64981ad6265SDimitry Andric   MachOConfig &MachOConfig = ConfigMgr.MachO;
65081ad6265SDimitry Andric   Config.InputFilename = Positional[0];
65181ad6265SDimitry Andric   Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
65281ad6265SDimitry Andric   if (InputArgs.hasArg(OBJCOPY_target) &&
65381ad6265SDimitry Andric       (InputArgs.hasArg(OBJCOPY_input_target) ||
65481ad6265SDimitry Andric        InputArgs.hasArg(OBJCOPY_output_target)))
65581ad6265SDimitry Andric     return createStringError(
65681ad6265SDimitry Andric         errc::invalid_argument,
65781ad6265SDimitry Andric         "--target cannot be used with --input-target or --output-target");
65881ad6265SDimitry Andric 
65981ad6265SDimitry Andric   if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
66081ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
66181ad6265SDimitry Andric                              "--regex and --wildcard are incompatible");
66281ad6265SDimitry Andric 
66381ad6265SDimitry Andric   MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
66481ad6265SDimitry Andric                                      ? MatchStyle::Regex
66581ad6265SDimitry Andric                                      : MatchStyle::Wildcard;
66681ad6265SDimitry Andric   MatchStyle SymbolMatchStyle
66781ad6265SDimitry Andric       = InputArgs.hasArg(OBJCOPY_regex)    ? MatchStyle::Regex
66881ad6265SDimitry Andric       : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard
66981ad6265SDimitry Andric                                            : MatchStyle::Literal;
67081ad6265SDimitry Andric   StringRef InputFormat, OutputFormat;
67181ad6265SDimitry Andric   if (InputArgs.hasArg(OBJCOPY_target)) {
67281ad6265SDimitry Andric     InputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
67381ad6265SDimitry Andric     OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
67481ad6265SDimitry Andric   } else {
67581ad6265SDimitry Andric     InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
67681ad6265SDimitry Andric     OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
67781ad6265SDimitry Andric   }
67881ad6265SDimitry Andric 
67981ad6265SDimitry Andric   // FIXME:  Currently, we ignore the target for non-binary/ihex formats
68081ad6265SDimitry Andric   // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the
68181ad6265SDimitry Andric   // format by llvm::object::createBinary regardless of the option value.
68281ad6265SDimitry Andric   Config.InputFormat = StringSwitch<FileFormat>(InputFormat)
68381ad6265SDimitry Andric                            .Case("binary", FileFormat::Binary)
68481ad6265SDimitry Andric                            .Case("ihex", FileFormat::IHex)
68581ad6265SDimitry Andric                            .Default(FileFormat::Unspecified);
68681ad6265SDimitry Andric 
68781ad6265SDimitry Andric   if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) {
68881ad6265SDimitry Andric     const uint8_t Invalid = 0xff;
68981ad6265SDimitry Andric     StringRef VisibilityStr =
69081ad6265SDimitry Andric         InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
69181ad6265SDimitry Andric 
69281ad6265SDimitry Andric     ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr)
69381ad6265SDimitry Andric                                         .Case("default", ELF::STV_DEFAULT)
69481ad6265SDimitry Andric                                         .Case("hidden", ELF::STV_HIDDEN)
69581ad6265SDimitry Andric                                         .Case("internal", ELF::STV_INTERNAL)
69681ad6265SDimitry Andric                                         .Case("protected", ELF::STV_PROTECTED)
69781ad6265SDimitry Andric                                         .Default(Invalid);
69881ad6265SDimitry Andric 
69981ad6265SDimitry Andric     if (ELFConfig.NewSymbolVisibility == Invalid)
70081ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
70181ad6265SDimitry Andric                                "'%s' is not a valid symbol visibility",
70281ad6265SDimitry Andric                                VisibilityStr.str().c_str());
70381ad6265SDimitry Andric   }
70481ad6265SDimitry Andric 
70581ad6265SDimitry Andric   for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) {
70681ad6265SDimitry Andric     StringRef Subsystem, Version;
70781ad6265SDimitry Andric     std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':');
70881ad6265SDimitry Andric     COFFConfig.Subsystem =
70981ad6265SDimitry Andric         StringSwitch<unsigned>(Subsystem.lower())
71081ad6265SDimitry Andric             .Case("boot_application",
71181ad6265SDimitry Andric                   COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
71281ad6265SDimitry Andric             .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
713*0fca6ea1SDimitry Andric             .Cases("efi_application", "efi-app",
714*0fca6ea1SDimitry Andric                    COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION)
715*0fca6ea1SDimitry Andric             .Cases("efi_boot_service_driver", "efi-bsd",
71681ad6265SDimitry Andric                    COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
71781ad6265SDimitry Andric             .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM)
718*0fca6ea1SDimitry Andric             .Cases("efi_runtime_driver", "efi-rtd",
71981ad6265SDimitry Andric                    COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
72081ad6265SDimitry Andric             .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE)
72181ad6265SDimitry Andric             .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI)
72281ad6265SDimitry Andric             .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
72381ad6265SDimitry Andric             .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN);
72481ad6265SDimitry Andric     if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN)
72581ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
72681ad6265SDimitry Andric                                "'%s' is not a valid subsystem",
72781ad6265SDimitry Andric                                Subsystem.str().c_str());
72881ad6265SDimitry Andric     if (!Version.empty()) {
72981ad6265SDimitry Andric       StringRef Major, Minor;
73081ad6265SDimitry Andric       std::tie(Major, Minor) = Version.split('.');
73181ad6265SDimitry Andric       unsigned Number;
73281ad6265SDimitry Andric       if (Major.getAsInteger(10, Number))
73381ad6265SDimitry Andric         return createStringError(errc::invalid_argument,
73481ad6265SDimitry Andric                                  "'%s' is not a valid subsystem major version",
73581ad6265SDimitry Andric                                  Major.str().c_str());
73681ad6265SDimitry Andric       COFFConfig.MajorSubsystemVersion = Number;
73781ad6265SDimitry Andric       Number = 0;
73881ad6265SDimitry Andric       if (!Minor.empty() && Minor.getAsInteger(10, Number))
73981ad6265SDimitry Andric         return createStringError(errc::invalid_argument,
74081ad6265SDimitry Andric                                  "'%s' is not a valid subsystem minor version",
74181ad6265SDimitry Andric                                  Minor.str().c_str());
74281ad6265SDimitry Andric       COFFConfig.MinorSubsystemVersion = Number;
74381ad6265SDimitry Andric     }
74481ad6265SDimitry Andric   }
74581ad6265SDimitry Andric 
74681ad6265SDimitry Andric   Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
74781ad6265SDimitry Andric                             .Case("binary", FileFormat::Binary)
74881ad6265SDimitry Andric                             .Case("ihex", FileFormat::IHex)
749*0fca6ea1SDimitry Andric                             .Case("srec", FileFormat::SREC)
75081ad6265SDimitry Andric                             .Default(FileFormat::Unspecified);
75181ad6265SDimitry Andric   if (Config.OutputFormat == FileFormat::Unspecified) {
75281ad6265SDimitry Andric     if (OutputFormat.empty()) {
75381ad6265SDimitry Andric       Config.OutputFormat = Config.InputFormat;
75481ad6265SDimitry Andric     } else {
75581ad6265SDimitry Andric       Expected<TargetInfo> Target =
75681ad6265SDimitry Andric           getOutputTargetInfoByTargetName(OutputFormat);
75781ad6265SDimitry Andric       if (!Target)
75881ad6265SDimitry Andric         return Target.takeError();
75981ad6265SDimitry Andric       Config.OutputFormat = Target->Format;
76081ad6265SDimitry Andric       Config.OutputArch = Target->Machine;
76181ad6265SDimitry Andric     }
76281ad6265SDimitry Andric   }
76381ad6265SDimitry Andric 
764972a253aSDimitry Andric   if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) {
765972a253aSDimitry Andric     Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue())
766bdd1243dSDimitry Andric                                  .Case("zlib", DebugCompressionType::Zlib)
767bdd1243dSDimitry Andric                                  .Case("zstd", DebugCompressionType::Zstd)
76881ad6265SDimitry Andric                                  .Default(DebugCompressionType::None);
769bdd1243dSDimitry Andric     if (Config.CompressionType == DebugCompressionType::None) {
77081ad6265SDimitry Andric       return createStringError(
77181ad6265SDimitry Andric           errc::invalid_argument,
77281ad6265SDimitry Andric           "invalid or unsupported --compress-debug-sections format: %s",
773972a253aSDimitry Andric           A->getValue());
774bdd1243dSDimitry Andric     }
775bdd1243dSDimitry Andric     if (const char *Reason = compression::getReasonIfUnsupported(
776bdd1243dSDimitry Andric             compression::formatFor(Config.CompressionType)))
777bdd1243dSDimitry Andric       return createStringError(errc::invalid_argument, Reason);
77881ad6265SDimitry Andric   }
77981ad6265SDimitry Andric 
780*0fca6ea1SDimitry Andric   for (const auto *A : InputArgs.filtered(OBJCOPY_compress_sections)) {
781*0fca6ea1SDimitry Andric     SmallVector<StringRef, 0> Fields;
782*0fca6ea1SDimitry Andric     StringRef(A->getValue()).split(Fields, '=');
783*0fca6ea1SDimitry Andric     if (Fields.size() != 2 || Fields[1].empty()) {
784*0fca6ea1SDimitry Andric       return createStringError(
785*0fca6ea1SDimitry Andric           errc::invalid_argument,
786*0fca6ea1SDimitry Andric           A->getSpelling() +
787*0fca6ea1SDimitry Andric               ": parse error, not 'section-glob=[none|zlib|zstd]'");
788*0fca6ea1SDimitry Andric     }
789*0fca6ea1SDimitry Andric 
790*0fca6ea1SDimitry Andric     auto Type = StringSwitch<DebugCompressionType>(Fields[1])
791*0fca6ea1SDimitry Andric                     .Case("zlib", DebugCompressionType::Zlib)
792*0fca6ea1SDimitry Andric                     .Case("zstd", DebugCompressionType::Zstd)
793*0fca6ea1SDimitry Andric                     .Default(DebugCompressionType::None);
794*0fca6ea1SDimitry Andric     if (Type == DebugCompressionType::None && Fields[1] != "none") {
795*0fca6ea1SDimitry Andric       return createStringError(
796*0fca6ea1SDimitry Andric           errc::invalid_argument,
797*0fca6ea1SDimitry Andric           "invalid or unsupported --compress-sections format: %s",
798*0fca6ea1SDimitry Andric           A->getValue());
799*0fca6ea1SDimitry Andric     }
800*0fca6ea1SDimitry Andric 
801*0fca6ea1SDimitry Andric     auto &P = Config.compressSections.emplace_back();
802*0fca6ea1SDimitry Andric     P.second = Type;
803*0fca6ea1SDimitry Andric     auto Matcher =
804*0fca6ea1SDimitry Andric         NameOrPattern::create(Fields[0], SectionMatchStyle, ErrorCallback);
805*0fca6ea1SDimitry Andric     // =none allows overriding a previous =zlib or =zstd. Reject negative
806*0fca6ea1SDimitry Andric     // patterns, which would be confusing.
807*0fca6ea1SDimitry Andric     if (Matcher && !Matcher->isPositiveMatch()) {
808*0fca6ea1SDimitry Andric       return createStringError(
809*0fca6ea1SDimitry Andric           errc::invalid_argument,
810*0fca6ea1SDimitry Andric           "--compress-sections: negative pattern is unsupported");
811*0fca6ea1SDimitry Andric     }
812*0fca6ea1SDimitry Andric     if (Error E = P.first.addMatcher(std::move(Matcher)))
813*0fca6ea1SDimitry Andric       return std::move(E);
814*0fca6ea1SDimitry Andric   }
815*0fca6ea1SDimitry Andric 
81681ad6265SDimitry Andric   Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
81781ad6265SDimitry Andric   // The gnu_debuglink's target is expected to not change or else its CRC would
81881ad6265SDimitry Andric   // become invalidated and get rejected. We can avoid recalculating the
81981ad6265SDimitry Andric   // checksum for every target file inside an archive by precomputing the CRC
82081ad6265SDimitry Andric   // here. This prevents a significant amount of I/O.
82181ad6265SDimitry Andric   if (!Config.AddGnuDebugLink.empty()) {
82281ad6265SDimitry Andric     auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink);
82381ad6265SDimitry Andric     if (!DebugOrErr)
82481ad6265SDimitry Andric       return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());
82581ad6265SDimitry Andric     auto Debug = std::move(*DebugOrErr);
82681ad6265SDimitry Andric     Config.GnuDebugLinkCRC32 =
82781ad6265SDimitry Andric         llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
82881ad6265SDimitry Andric   }
82981ad6265SDimitry Andric   Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
830*0fca6ea1SDimitry Andric 
83181ad6265SDimitry Andric   Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
832*0fca6ea1SDimitry Andric   Config.SymbolsPrefixRemove =
833*0fca6ea1SDimitry Andric       InputArgs.getLastArgValue(OBJCOPY_remove_symbol_prefix);
834*0fca6ea1SDimitry Andric 
83581ad6265SDimitry Andric   Config.AllocSectionsPrefix =
83681ad6265SDimitry Andric       InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
83781ad6265SDimitry Andric   if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
83881ad6265SDimitry Andric     Config.ExtractPartition = Arg->getValue();
83981ad6265SDimitry Andric 
8405f757f3fSDimitry Andric   if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) {
8415f757f3fSDimitry Andric     if (Config.OutputFormat != FileFormat::Binary)
8425f757f3fSDimitry Andric       return createStringError(
8435f757f3fSDimitry Andric           errc::invalid_argument,
8445f757f3fSDimitry Andric           "'--gap-fill' is only supported for binary output");
8455f757f3fSDimitry Andric     ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue());
8465f757f3fSDimitry Andric     if (!Val)
8475f757f3fSDimitry Andric       return createStringError(Val.getError(), "--gap-fill: bad number: %s",
8485f757f3fSDimitry Andric                                A->getValue());
8495f757f3fSDimitry Andric     uint8_t ByteVal = Val.get();
8505f757f3fSDimitry Andric     if (ByteVal != Val.get())
8515f757f3fSDimitry Andric       return createStringError(std::errc::value_too_large,
8525f757f3fSDimitry Andric                                "gap-fill value %s is out of range (0 to 0xff)",
8535f757f3fSDimitry Andric                                A->getValue());
8545f757f3fSDimitry Andric     Config.GapFill = ByteVal;
8555f757f3fSDimitry Andric   }
8565f757f3fSDimitry Andric 
8575f757f3fSDimitry Andric   if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) {
8585f757f3fSDimitry Andric     if (Config.OutputFormat != FileFormat::Binary)
8595f757f3fSDimitry Andric       return createStringError(
8605f757f3fSDimitry Andric           errc::invalid_argument,
8615f757f3fSDimitry Andric           "'--pad-to' is only supported for binary output");
8625f757f3fSDimitry Andric     ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue());
8635f757f3fSDimitry Andric     if (!Addr)
8645f757f3fSDimitry Andric       return createStringError(Addr.getError(), "--pad-to: bad number: %s",
8655f757f3fSDimitry Andric                                A->getValue());
8665f757f3fSDimitry Andric     Config.PadTo = *Addr;
8675f757f3fSDimitry Andric   }
8685f757f3fSDimitry Andric 
869*0fca6ea1SDimitry Andric   if (const auto *Arg = InputArgs.getLastArg(OBJCOPY_change_section_lma)) {
870*0fca6ea1SDimitry Andric     Expected<int64_t> LMAValue =
871*0fca6ea1SDimitry Andric         parseChangeSectionLMA(Arg->getValue(), Arg->getSpelling());
872*0fca6ea1SDimitry Andric     if (!LMAValue)
873*0fca6ea1SDimitry Andric       return LMAValue.takeError();
874*0fca6ea1SDimitry Andric     Config.ChangeSectionLMAValAll = *LMAValue;
875*0fca6ea1SDimitry Andric   }
876*0fca6ea1SDimitry Andric 
877bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
87881ad6265SDimitry Andric     if (!StringRef(Arg->getValue()).contains('='))
87981ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
88081ad6265SDimitry Andric                                "bad format for --redefine-sym");
88181ad6265SDimitry Andric     auto Old2New = StringRef(Arg->getValue()).split('=');
88281ad6265SDimitry Andric     if (!Config.SymbolsToRename.insert(Old2New).second)
88381ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
88481ad6265SDimitry Andric                                "multiple redefinition of symbol '%s'",
88581ad6265SDimitry Andric                                Old2New.first.str().c_str());
88681ad6265SDimitry Andric   }
88781ad6265SDimitry Andric 
888bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
88981ad6265SDimitry Andric     if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
89081ad6265SDimitry Andric                                              Arg->getValue()))
89181ad6265SDimitry Andric       return std::move(E);
89281ad6265SDimitry Andric 
893bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
89481ad6265SDimitry Andric     Expected<SectionRename> SR =
89581ad6265SDimitry Andric         parseRenameSectionValue(StringRef(Arg->getValue()));
89681ad6265SDimitry Andric     if (!SR)
89781ad6265SDimitry Andric       return SR.takeError();
89881ad6265SDimitry Andric     if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
89981ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
90081ad6265SDimitry Andric                                "multiple renames of section '%s'",
90181ad6265SDimitry Andric                                SR->OriginalName.str().c_str());
90281ad6265SDimitry Andric   }
903bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
90481ad6265SDimitry Andric     Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
905753f127fSDimitry Andric         parseSetSectionAttribute("--set-section-alignment", Arg->getValue());
90681ad6265SDimitry Andric     if (!NameAndAlign)
90781ad6265SDimitry Andric       return NameAndAlign.takeError();
90881ad6265SDimitry Andric     Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
90981ad6265SDimitry Andric   }
910bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
91181ad6265SDimitry Andric     Expected<SectionFlagsUpdate> SFU =
91281ad6265SDimitry Andric         parseSetSectionFlagValue(Arg->getValue());
91381ad6265SDimitry Andric     if (!SFU)
91481ad6265SDimitry Andric       return SFU.takeError();
91581ad6265SDimitry Andric     if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
91681ad6265SDimitry Andric       return createStringError(
91781ad6265SDimitry Andric           errc::invalid_argument,
91881ad6265SDimitry Andric           "--set-section-flags set multiple times for section '%s'",
91981ad6265SDimitry Andric           SFU->Name.str().c_str());
92081ad6265SDimitry Andric   }
921bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) {
922753f127fSDimitry Andric     Expected<std::pair<StringRef, uint64_t>> NameAndType =
923753f127fSDimitry Andric         parseSetSectionAttribute("--set-section-type", Arg->getValue());
924753f127fSDimitry Andric     if (!NameAndType)
925753f127fSDimitry Andric       return NameAndType.takeError();
926753f127fSDimitry Andric     Config.SetSectionType[NameAndType->first] = NameAndType->second;
927753f127fSDimitry Andric   }
928753f127fSDimitry Andric   // Prohibit combinations of --set-section-{flags,type} when the section name
929753f127fSDimitry Andric   // is used as the destination of a --rename-section.
93081ad6265SDimitry Andric   for (const auto &E : Config.SectionsToRename) {
93181ad6265SDimitry Andric     const SectionRename &SR = E.second;
932753f127fSDimitry Andric     auto Err = [&](const char *Option) {
93381ad6265SDimitry Andric       return createStringError(
93481ad6265SDimitry Andric           errc::invalid_argument,
935753f127fSDimitry Andric           "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option,
93681ad6265SDimitry Andric           SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
93781ad6265SDimitry Andric           SR.NewName.str().c_str());
938753f127fSDimitry Andric     };
939753f127fSDimitry Andric     if (Config.SetSectionFlags.count(SR.NewName))
940753f127fSDimitry Andric       return Err("flags");
941753f127fSDimitry Andric     if (Config.SetSectionType.count(SR.NewName))
942753f127fSDimitry Andric       return Err("type");
94381ad6265SDimitry Andric   }
94481ad6265SDimitry Andric 
945bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section))
94681ad6265SDimitry Andric     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
94781ad6265SDimitry Andric             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
94881ad6265SDimitry Andric       return std::move(E);
949bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section))
95081ad6265SDimitry Andric     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
95181ad6265SDimitry Andric             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
95281ad6265SDimitry Andric       return std::move(E);
953bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section))
95481ad6265SDimitry Andric     if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
95581ad6265SDimitry Andric             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
95681ad6265SDimitry Andric       return std::move(E);
957bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) {
95881ad6265SDimitry Andric     if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section",
95981ad6265SDimitry Andric                                        Config.AddSection))
96081ad6265SDimitry Andric       return std::move(Err);
96181ad6265SDimitry Andric   }
962bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) {
96381ad6265SDimitry Andric     if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section",
96481ad6265SDimitry Andric                                        Config.UpdateSection))
96581ad6265SDimitry Andric       return std::move(Err);
96681ad6265SDimitry Andric   }
96781ad6265SDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
96881ad6265SDimitry Andric     StringRef Value(Arg->getValue());
96981ad6265SDimitry Andric     if (Value.split('=').second.empty())
97081ad6265SDimitry Andric       return createStringError(
97181ad6265SDimitry Andric           errc::invalid_argument,
97281ad6265SDimitry Andric           "bad format for --dump-section, expected section=file");
97381ad6265SDimitry Andric     Config.DumpSection.push_back(Value);
97481ad6265SDimitry Andric   }
97581ad6265SDimitry Andric   Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
97681ad6265SDimitry Andric   Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
97781ad6265SDimitry Andric   Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
97881ad6265SDimitry Andric   Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
97981ad6265SDimitry Andric   Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
98081ad6265SDimitry Andric   Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
98181ad6265SDimitry Andric   Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
98281ad6265SDimitry Andric   Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
98381ad6265SDimitry Andric   Config.ExtractMainPartition =
98481ad6265SDimitry Andric       InputArgs.hasArg(OBJCOPY_extract_main_partition);
98581ad6265SDimitry Andric   ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
98681ad6265SDimitry Andric   Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
98781ad6265SDimitry Andric   if (auto *Arg =
98881ad6265SDimitry Andric           InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
98981ad6265SDimitry Andric     Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all)
99081ad6265SDimitry Andric                              ? DiscardType::All
99181ad6265SDimitry Andric                              : DiscardType::Locals;
99281ad6265SDimitry Andric   }
993*0fca6ea1SDimitry Andric 
994*0fca6ea1SDimitry Andric   ELFConfig.VerifyNoteSections = InputArgs.hasFlag(
995*0fca6ea1SDimitry Andric       OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true);
996*0fca6ea1SDimitry Andric 
99781ad6265SDimitry Andric   Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
99881ad6265SDimitry Andric   ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
99981ad6265SDimitry Andric   MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
100081ad6265SDimitry Andric   Config.DecompressDebugSections =
100181ad6265SDimitry Andric       InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
100281ad6265SDimitry Andric   if (Config.DiscardMode == DiscardType::All) {
100381ad6265SDimitry Andric     Config.StripDebug = true;
100481ad6265SDimitry Andric     ELFConfig.KeepFileSymbols = true;
100581ad6265SDimitry Andric   }
1006bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
100781ad6265SDimitry Andric     if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
100881ad6265SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
100981ad6265SDimitry Andric       return std::move(E);
1010bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
101181ad6265SDimitry Andric     if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
101281ad6265SDimitry Andric                                      Arg->getValue(), SymbolMatchStyle,
101381ad6265SDimitry Andric                                      ErrorCallback))
101481ad6265SDimitry Andric       return std::move(E);
1015bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
101681ad6265SDimitry Andric     if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
101781ad6265SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
101881ad6265SDimitry Andric       return std::move(E);
1019bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
102081ad6265SDimitry Andric     if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
102181ad6265SDimitry Andric                                      Arg->getValue(), SymbolMatchStyle,
102281ad6265SDimitry Andric                                      ErrorCallback))
102381ad6265SDimitry Andric       return std::move(E);
1024bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
102581ad6265SDimitry Andric     if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
102681ad6265SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
102781ad6265SDimitry Andric       return std::move(E);
1028bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
102981ad6265SDimitry Andric     if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
103081ad6265SDimitry Andric                                      Arg->getValue(), SymbolMatchStyle,
103181ad6265SDimitry Andric                                      ErrorCallback))
103281ad6265SDimitry Andric       return std::move(E);
1033bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
103481ad6265SDimitry Andric     if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
103581ad6265SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
103681ad6265SDimitry Andric       return std::move(E);
1037bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
103881ad6265SDimitry Andric     if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
103981ad6265SDimitry Andric                                      Arg->getValue(), SymbolMatchStyle,
104081ad6265SDimitry Andric                                      ErrorCallback))
104181ad6265SDimitry Andric       return std::move(E);
1042bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
104381ad6265SDimitry Andric     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
104481ad6265SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
104581ad6265SDimitry Andric       return std::move(E);
1046bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
104781ad6265SDimitry Andric     if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
104881ad6265SDimitry Andric                                      Arg->getValue(), SymbolMatchStyle,
104981ad6265SDimitry Andric                                      ErrorCallback))
105081ad6265SDimitry Andric       return std::move(E);
1051bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
105281ad6265SDimitry Andric     if (Error E =
105381ad6265SDimitry Andric             Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
105481ad6265SDimitry Andric                 Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
105581ad6265SDimitry Andric       return std::move(E);
1056bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
105781ad6265SDimitry Andric     if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
105881ad6265SDimitry Andric                                      Arg->getValue(), SymbolMatchStyle,
105981ad6265SDimitry Andric                                      ErrorCallback))
106081ad6265SDimitry Andric       return std::move(E);
1061bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
106281ad6265SDimitry Andric     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
106381ad6265SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
106481ad6265SDimitry Andric       return std::move(E);
1065bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
106681ad6265SDimitry Andric     if (Error E =
106781ad6265SDimitry Andric             addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
106881ad6265SDimitry Andric                                SymbolMatchStyle, ErrorCallback))
106981ad6265SDimitry Andric       return std::move(E);
1070*0fca6ea1SDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol))
1071*0fca6ea1SDimitry Andric     if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create(
1072*0fca6ea1SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1073*0fca6ea1SDimitry Andric       return std::move(E);
1074*0fca6ea1SDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols))
1075*0fca6ea1SDimitry Andric     if (Error E =
1076*0fca6ea1SDimitry Andric             addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(),
1077*0fca6ea1SDimitry Andric                                SymbolMatchStyle, ErrorCallback))
1078*0fca6ea1SDimitry Andric       return std::move(E);
107981ad6265SDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
108081ad6265SDimitry Andric     Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
108181ad6265SDimitry Andric     if (!SymInfo)
108281ad6265SDimitry Andric       return SymInfo.takeError();
108381ad6265SDimitry Andric 
108481ad6265SDimitry Andric     Config.SymbolsToAdd.push_back(*SymInfo);
108581ad6265SDimitry Andric   }
1086*0fca6ea1SDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbol_visibility)) {
1087*0fca6ea1SDimitry Andric     if (!StringRef(Arg->getValue()).contains('='))
1088*0fca6ea1SDimitry Andric       return createStringError(errc::invalid_argument,
1089*0fca6ea1SDimitry Andric                                "bad format for --set-symbol-visibility");
1090*0fca6ea1SDimitry Andric     auto [Sym, Visibility] = StringRef(Arg->getValue()).split('=');
1091*0fca6ea1SDimitry Andric     Expected<uint8_t> Type = parseVisibilityType(Visibility);
1092*0fca6ea1SDimitry Andric     if (!Type)
1093*0fca6ea1SDimitry Andric       return Type.takeError();
1094*0fca6ea1SDimitry Andric     ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type);
1095*0fca6ea1SDimitry Andric     if (Error E = ELFConfig.SymbolsToSetVisibility.back().first.addMatcher(
1096*0fca6ea1SDimitry Andric             NameOrPattern::create(Sym, SymbolMatchStyle, ErrorCallback)))
1097*0fca6ea1SDimitry Andric       return std::move(E);
1098*0fca6ea1SDimitry Andric   }
1099*0fca6ea1SDimitry Andric   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbols_visibility)) {
1100*0fca6ea1SDimitry Andric     if (!StringRef(Arg->getValue()).contains('='))
1101*0fca6ea1SDimitry Andric       return createStringError(errc::invalid_argument,
1102*0fca6ea1SDimitry Andric                                "bad format for --set-symbols-visibility");
1103*0fca6ea1SDimitry Andric     auto [File, Visibility] = StringRef(Arg->getValue()).split('=');
1104*0fca6ea1SDimitry Andric     Expected<uint8_t> Type = parseVisibilityType(Visibility);
1105*0fca6ea1SDimitry Andric     if (!Type)
1106*0fca6ea1SDimitry Andric       return Type.takeError();
1107*0fca6ea1SDimitry Andric     ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type);
1108*0fca6ea1SDimitry Andric     if (Error E =
1109*0fca6ea1SDimitry Andric             addSymbolsFromFile(ELFConfig.SymbolsToSetVisibility.back().first,
1110*0fca6ea1SDimitry Andric                                DC.Alloc, File, SymbolMatchStyle, ErrorCallback))
1111*0fca6ea1SDimitry Andric       return std::move(E);
1112*0fca6ea1SDimitry Andric   }
111381ad6265SDimitry Andric 
111481ad6265SDimitry Andric   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
111581ad6265SDimitry Andric 
111681ad6265SDimitry Andric   Config.DeterministicArchives = InputArgs.hasFlag(
111781ad6265SDimitry Andric       OBJCOPY_enable_deterministic_archives,
111881ad6265SDimitry Andric       OBJCOPY_disable_deterministic_archives, /*default=*/true);
111981ad6265SDimitry Andric 
112081ad6265SDimitry Andric   Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
112181ad6265SDimitry Andric 
112281ad6265SDimitry Andric   if (Config.PreserveDates &&
112381ad6265SDimitry Andric       (Config.OutputFilename == "-" || Config.InputFilename == "-"))
112481ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
112581ad6265SDimitry Andric                              "--preserve-dates requires a file");
112681ad6265SDimitry Andric 
1127bdd1243dSDimitry Andric   for (auto *Arg : InputArgs)
112881ad6265SDimitry Andric     if (Arg->getOption().matches(OBJCOPY_set_start)) {
112981ad6265SDimitry Andric       auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
113081ad6265SDimitry Andric       if (!EAddr)
113181ad6265SDimitry Andric         return createStringError(
113281ad6265SDimitry Andric             EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
113381ad6265SDimitry Andric 
113481ad6265SDimitry Andric       ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
113581ad6265SDimitry Andric     } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
113681ad6265SDimitry Andric       auto EIncr = getAsInteger<int64_t>(Arg->getValue());
113781ad6265SDimitry Andric       if (!EIncr)
113881ad6265SDimitry Andric         return createStringError(EIncr.getError(),
113981ad6265SDimitry Andric                                  "bad entry point increment: '%s'",
114081ad6265SDimitry Andric                                  Arg->getValue());
114181ad6265SDimitry Andric       auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr)
114281ad6265SDimitry Andric                                       : [](uint64_t A) { return A; };
114381ad6265SDimitry Andric       ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
114481ad6265SDimitry Andric         return Expr(EAddr) + *EIncr;
114581ad6265SDimitry Andric       };
114681ad6265SDimitry Andric     }
114781ad6265SDimitry Andric 
114881ad6265SDimitry Andric   if (Config.DecompressDebugSections &&
114981ad6265SDimitry Andric       Config.CompressionType != DebugCompressionType::None) {
115081ad6265SDimitry Andric     return createStringError(
115181ad6265SDimitry Andric         errc::invalid_argument,
115281ad6265SDimitry Andric         "cannot specify both --compress-debug-sections and "
115381ad6265SDimitry Andric         "--decompress-debug-sections");
115481ad6265SDimitry Andric   }
115581ad6265SDimitry Andric 
115681ad6265SDimitry Andric   if (Config.ExtractPartition && Config.ExtractMainPartition)
115781ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
115881ad6265SDimitry Andric                              "cannot specify --extract-partition together with "
115981ad6265SDimitry Andric                              "--extract-main-partition");
116081ad6265SDimitry Andric 
116181ad6265SDimitry Andric   DC.CopyConfigs.push_back(std::move(ConfigMgr));
116281ad6265SDimitry Andric   return std::move(DC);
116381ad6265SDimitry Andric }
116481ad6265SDimitry Andric 
116581ad6265SDimitry Andric // parseInstallNameToolOptions returns the config and sets the input arguments.
116681ad6265SDimitry Andric // If a help flag is set then parseInstallNameToolOptions will print the help
116781ad6265SDimitry Andric // messege and exit.
116881ad6265SDimitry Andric Expected<DriverConfig>
116981ad6265SDimitry Andric objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
117081ad6265SDimitry Andric   DriverConfig DC;
117181ad6265SDimitry Andric   ConfigManager ConfigMgr;
117281ad6265SDimitry Andric   CommonConfig &Config = ConfigMgr.Common;
117381ad6265SDimitry Andric   MachOConfig &MachOConfig = ConfigMgr.MachO;
117481ad6265SDimitry Andric   InstallNameToolOptTable T;
117581ad6265SDimitry Andric   unsigned MissingArgumentIndex, MissingArgumentCount;
117681ad6265SDimitry Andric   llvm::opt::InputArgList InputArgs =
117781ad6265SDimitry Andric       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
117881ad6265SDimitry Andric 
117981ad6265SDimitry Andric   if (MissingArgumentCount)
118081ad6265SDimitry Andric     return createStringError(
118181ad6265SDimitry Andric         errc::invalid_argument,
118281ad6265SDimitry Andric         "missing argument to " +
118381ad6265SDimitry Andric             StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
118481ad6265SDimitry Andric             " option");
118581ad6265SDimitry Andric 
118681ad6265SDimitry Andric   if (InputArgs.size() == 0) {
118781ad6265SDimitry Andric     printHelp(T, errs(), ToolType::InstallNameTool);
118881ad6265SDimitry Andric     exit(1);
118981ad6265SDimitry Andric   }
119081ad6265SDimitry Andric 
119181ad6265SDimitry Andric   if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
119281ad6265SDimitry Andric     printHelp(T, outs(), ToolType::InstallNameTool);
119381ad6265SDimitry Andric     exit(0);
119481ad6265SDimitry Andric   }
119581ad6265SDimitry Andric 
119681ad6265SDimitry Andric   if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
119781ad6265SDimitry Andric     outs() << "llvm-install-name-tool, compatible with cctools "
119881ad6265SDimitry Andric               "install_name_tool\n";
119981ad6265SDimitry Andric     cl::PrintVersionMessage();
120081ad6265SDimitry Andric     exit(0);
120181ad6265SDimitry Andric   }
120281ad6265SDimitry Andric 
1203bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
120481ad6265SDimitry Andric     MachOConfig.RPathToAdd.push_back(Arg->getValue());
120581ad6265SDimitry Andric 
120681ad6265SDimitry Andric   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
120781ad6265SDimitry Andric     MachOConfig.RPathToPrepend.push_back(Arg->getValue());
120881ad6265SDimitry Andric 
1209bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
121081ad6265SDimitry Andric     StringRef RPath = Arg->getValue();
121181ad6265SDimitry Andric 
121281ad6265SDimitry Andric     // Cannot add and delete the same rpath at the same time.
121381ad6265SDimitry Andric     if (is_contained(MachOConfig.RPathToAdd, RPath))
121481ad6265SDimitry Andric       return createStringError(
121581ad6265SDimitry Andric           errc::invalid_argument,
121681ad6265SDimitry Andric           "cannot specify both -add_rpath '%s' and -delete_rpath '%s'",
121781ad6265SDimitry Andric           RPath.str().c_str(), RPath.str().c_str());
121881ad6265SDimitry Andric     if (is_contained(MachOConfig.RPathToPrepend, RPath))
121981ad6265SDimitry Andric       return createStringError(
122081ad6265SDimitry Andric           errc::invalid_argument,
122181ad6265SDimitry Andric           "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'",
122281ad6265SDimitry Andric           RPath.str().c_str(), RPath.str().c_str());
122381ad6265SDimitry Andric 
122481ad6265SDimitry Andric     MachOConfig.RPathsToRemove.insert(RPath);
122581ad6265SDimitry Andric   }
122681ad6265SDimitry Andric 
122781ad6265SDimitry Andric   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) {
122881ad6265SDimitry Andric     StringRef Old = Arg->getValue(0);
122981ad6265SDimitry Andric     StringRef New = Arg->getValue(1);
123081ad6265SDimitry Andric 
123181ad6265SDimitry Andric     auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; };
123281ad6265SDimitry Andric 
123381ad6265SDimitry Andric     // Cannot specify duplicate -rpath entries
123481ad6265SDimitry Andric     auto It1 = find_if(
123581ad6265SDimitry Andric         MachOConfig.RPathsToUpdate,
123681ad6265SDimitry Andric         [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) {
123781ad6265SDimitry Andric           return Match(OldNew.getFirst()) || Match(OldNew.getSecond());
123881ad6265SDimitry Andric         });
123981ad6265SDimitry Andric     if (It1 != MachOConfig.RPathsToUpdate.end())
124081ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
124181ad6265SDimitry Andric                                "cannot specify both -rpath '" +
124281ad6265SDimitry Andric                                    It1->getFirst() + "' '" + It1->getSecond() +
124381ad6265SDimitry Andric                                    "' and -rpath '" + Old + "' '" + New + "'");
124481ad6265SDimitry Andric 
124581ad6265SDimitry Andric     // Cannot specify the same rpath under both -delete_rpath and -rpath
124681ad6265SDimitry Andric     auto It2 = find_if(MachOConfig.RPathsToRemove, Match);
124781ad6265SDimitry Andric     if (It2 != MachOConfig.RPathsToRemove.end())
124881ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
124981ad6265SDimitry Andric                                "cannot specify both -delete_rpath '" + *It2 +
125081ad6265SDimitry Andric                                    "' and -rpath '" + Old + "' '" + New + "'");
125181ad6265SDimitry Andric 
125281ad6265SDimitry Andric     // Cannot specify the same rpath under both -add_rpath and -rpath
125381ad6265SDimitry Andric     auto It3 = find_if(MachOConfig.RPathToAdd, Match);
125481ad6265SDimitry Andric     if (It3 != MachOConfig.RPathToAdd.end())
125581ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
125681ad6265SDimitry Andric                                "cannot specify both -add_rpath '" + *It3 +
125781ad6265SDimitry Andric                                    "' and -rpath '" + Old + "' '" + New + "'");
125881ad6265SDimitry Andric 
125981ad6265SDimitry Andric     // Cannot specify the same rpath under both -prepend_rpath and -rpath.
126081ad6265SDimitry Andric     auto It4 = find_if(MachOConfig.RPathToPrepend, Match);
126181ad6265SDimitry Andric     if (It4 != MachOConfig.RPathToPrepend.end())
126281ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
126381ad6265SDimitry Andric                                "cannot specify both -prepend_rpath '" + *It4 +
126481ad6265SDimitry Andric                                    "' and -rpath '" + Old + "' '" + New + "'");
126581ad6265SDimitry Andric 
126681ad6265SDimitry Andric     MachOConfig.RPathsToUpdate.insert({Old, New});
126781ad6265SDimitry Andric   }
126881ad6265SDimitry Andric 
126981ad6265SDimitry Andric   if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) {
127081ad6265SDimitry Andric     MachOConfig.SharedLibId = Arg->getValue();
127181ad6265SDimitry Andric     if (MachOConfig.SharedLibId->empty())
127281ad6265SDimitry Andric       return createStringError(errc::invalid_argument,
127381ad6265SDimitry Andric                                "cannot specify an empty id");
127481ad6265SDimitry Andric   }
127581ad6265SDimitry Andric 
127681ad6265SDimitry Andric   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change))
127781ad6265SDimitry Andric     MachOConfig.InstallNamesToUpdate.insert(
127881ad6265SDimitry Andric         {Arg->getValue(0), Arg->getValue(1)});
127981ad6265SDimitry Andric 
128081ad6265SDimitry Andric   MachOConfig.RemoveAllRpaths =
128181ad6265SDimitry Andric       InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);
128281ad6265SDimitry Andric 
128381ad6265SDimitry Andric   SmallVector<StringRef, 2> Positional;
1284bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
128581ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "unknown argument '%s'",
128681ad6265SDimitry Andric                              Arg->getAsString(InputArgs).c_str());
1287bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
128881ad6265SDimitry Andric     Positional.push_back(Arg->getValue());
128981ad6265SDimitry Andric   if (Positional.empty())
129081ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "no input file specified");
129181ad6265SDimitry Andric   if (Positional.size() > 1)
129281ad6265SDimitry Andric     return createStringError(
129381ad6265SDimitry Andric         errc::invalid_argument,
129481ad6265SDimitry Andric         "llvm-install-name-tool expects a single input file");
129581ad6265SDimitry Andric   Config.InputFilename = Positional[0];
129681ad6265SDimitry Andric   Config.OutputFilename = Positional[0];
129781ad6265SDimitry Andric 
1298*0fca6ea1SDimitry Andric   Expected<OwningBinary<Binary>> BinaryOrErr =
1299*0fca6ea1SDimitry Andric       createBinary(Config.InputFilename);
1300*0fca6ea1SDimitry Andric   if (!BinaryOrErr)
1301*0fca6ea1SDimitry Andric     return createFileError(Config.InputFilename, BinaryOrErr.takeError());
1302*0fca6ea1SDimitry Andric   auto *Binary = (*BinaryOrErr).getBinary();
1303*0fca6ea1SDimitry Andric   if (!Binary->isMachO() && !Binary->isMachOUniversalBinary())
1304*0fca6ea1SDimitry Andric     return createStringError(errc::invalid_argument,
1305*0fca6ea1SDimitry Andric                              "input file: %s is not a Mach-O file",
1306*0fca6ea1SDimitry Andric                              Config.InputFilename.str().c_str());
1307*0fca6ea1SDimitry Andric 
130881ad6265SDimitry Andric   DC.CopyConfigs.push_back(std::move(ConfigMgr));
130981ad6265SDimitry Andric   return std::move(DC);
131081ad6265SDimitry Andric }
131181ad6265SDimitry Andric 
131281ad6265SDimitry Andric Expected<DriverConfig>
131381ad6265SDimitry Andric objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
131481ad6265SDimitry Andric                                   function_ref<Error(Error)> ErrorCallback) {
131581ad6265SDimitry Andric   DriverConfig DC;
131681ad6265SDimitry Andric   ConfigManager ConfigMgr;
131781ad6265SDimitry Andric   CommonConfig &Config = ConfigMgr.Common;
131881ad6265SDimitry Andric   MachOConfig &MachOConfig = ConfigMgr.MachO;
131981ad6265SDimitry Andric   BitcodeStripOptTable T;
132081ad6265SDimitry Andric   unsigned MissingArgumentIndex, MissingArgumentCount;
132181ad6265SDimitry Andric   opt::InputArgList InputArgs =
132281ad6265SDimitry Andric       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
132381ad6265SDimitry Andric 
132481ad6265SDimitry Andric   if (InputArgs.size() == 0) {
132581ad6265SDimitry Andric     printHelp(T, errs(), ToolType::BitcodeStrip);
132681ad6265SDimitry Andric     exit(1);
132781ad6265SDimitry Andric   }
132881ad6265SDimitry Andric 
132981ad6265SDimitry Andric   if (InputArgs.hasArg(BITCODE_STRIP_help)) {
133081ad6265SDimitry Andric     printHelp(T, outs(), ToolType::BitcodeStrip);
133181ad6265SDimitry Andric     exit(0);
133281ad6265SDimitry Andric   }
133381ad6265SDimitry Andric 
133481ad6265SDimitry Andric   if (InputArgs.hasArg(BITCODE_STRIP_version)) {
133581ad6265SDimitry Andric     outs() << "llvm-bitcode-strip, compatible with cctools "
133681ad6265SDimitry Andric               "bitcode_strip\n";
133781ad6265SDimitry Andric     cl::PrintVersionMessage();
133881ad6265SDimitry Andric     exit(0);
133981ad6265SDimitry Andric   }
134081ad6265SDimitry Andric 
134181ad6265SDimitry Andric   for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN))
134281ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "unknown argument '%s'",
134381ad6265SDimitry Andric                              Arg->getAsString(InputArgs).c_str());
134481ad6265SDimitry Andric 
134581ad6265SDimitry Andric   SmallVector<StringRef, 2> Positional;
134681ad6265SDimitry Andric   for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
134781ad6265SDimitry Andric     Positional.push_back(Arg->getValue());
134881ad6265SDimitry Andric   if (Positional.size() > 1)
134981ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
135081ad6265SDimitry Andric                              "llvm-bitcode-strip expects a single input file");
135181ad6265SDimitry Andric   assert(!Positional.empty());
135281ad6265SDimitry Andric   Config.InputFilename = Positional[0];
135381ad6265SDimitry Andric 
135481ad6265SDimitry Andric   if (!InputArgs.hasArg(BITCODE_STRIP_output)) {
135581ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
135681ad6265SDimitry Andric                              "-o is a required argument");
135781ad6265SDimitry Andric   }
135881ad6265SDimitry Andric   Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output);
135981ad6265SDimitry Andric 
136081ad6265SDimitry Andric   if (!InputArgs.hasArg(BITCODE_STRIP_remove))
136181ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "no action specified");
136281ad6265SDimitry Andric 
136381ad6265SDimitry Andric   // We only support -r for now, which removes all bitcode sections and
136481ad6265SDimitry Andric   // the __LLVM segment if it's now empty.
136581ad6265SDimitry Andric   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1366bdd1243dSDimitry Andric       "__LLVM,__asm", MatchStyle::Literal, ErrorCallback)));
1367bdd1243dSDimitry Andric   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1368bdd1243dSDimitry Andric       "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback)));
1369bdd1243dSDimitry Andric   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
137081ad6265SDimitry Andric       "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback)));
1371bdd1243dSDimitry Andric   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1372bdd1243dSDimitry Andric       "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback)));
1373bdd1243dSDimitry Andric   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1374bdd1243dSDimitry Andric       "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback)));
137581ad6265SDimitry Andric   MachOConfig.EmptySegmentsToRemove.insert("__LLVM");
137681ad6265SDimitry Andric 
137781ad6265SDimitry Andric   DC.CopyConfigs.push_back(std::move(ConfigMgr));
137881ad6265SDimitry Andric   return std::move(DC);
137981ad6265SDimitry Andric }
138081ad6265SDimitry Andric 
138181ad6265SDimitry Andric // parseStripOptions returns the config and sets the input arguments. If a
138281ad6265SDimitry Andric // help flag is set then parseStripOptions will print the help messege and
138381ad6265SDimitry Andric // exit.
138481ad6265SDimitry Andric Expected<DriverConfig>
138581ad6265SDimitry Andric objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
138681ad6265SDimitry Andric                            function_ref<Error(Error)> ErrorCallback) {
138781ad6265SDimitry Andric   const char *const *DashDash =
1388bdd1243dSDimitry Andric       llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
1389bdd1243dSDimitry Andric   ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
139081ad6265SDimitry Andric   if (DashDash != RawArgsArr.end())
139181ad6265SDimitry Andric     DashDash = std::next(DashDash);
139281ad6265SDimitry Andric 
139381ad6265SDimitry Andric   StripOptTable T;
139481ad6265SDimitry Andric   unsigned MissingArgumentIndex, MissingArgumentCount;
139581ad6265SDimitry Andric   llvm::opt::InputArgList InputArgs =
139681ad6265SDimitry Andric       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
139781ad6265SDimitry Andric 
139881ad6265SDimitry Andric   if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
139981ad6265SDimitry Andric     printHelp(T, errs(), ToolType::Strip);
140081ad6265SDimitry Andric     exit(1);
140181ad6265SDimitry Andric   }
140281ad6265SDimitry Andric 
140381ad6265SDimitry Andric   if (InputArgs.hasArg(STRIP_help)) {
140481ad6265SDimitry Andric     printHelp(T, outs(), ToolType::Strip);
140581ad6265SDimitry Andric     exit(0);
140681ad6265SDimitry Andric   }
140781ad6265SDimitry Andric 
140881ad6265SDimitry Andric   if (InputArgs.hasArg(STRIP_version)) {
140981ad6265SDimitry Andric     outs() << "llvm-strip, compatible with GNU strip\n";
141081ad6265SDimitry Andric     cl::PrintVersionMessage();
141181ad6265SDimitry Andric     exit(0);
141281ad6265SDimitry Andric   }
141381ad6265SDimitry Andric 
141481ad6265SDimitry Andric   SmallVector<StringRef, 2> Positional;
1415bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
141681ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "unknown argument '%s'",
141781ad6265SDimitry Andric                              Arg->getAsString(InputArgs).c_str());
1418bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
141981ad6265SDimitry Andric     Positional.push_back(Arg->getValue());
142081ad6265SDimitry Andric   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
142181ad6265SDimitry Andric 
142281ad6265SDimitry Andric   if (Positional.empty())
142381ad6265SDimitry Andric     return createStringError(errc::invalid_argument, "no input file specified");
142481ad6265SDimitry Andric 
142581ad6265SDimitry Andric   if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
142681ad6265SDimitry Andric     return createStringError(
142781ad6265SDimitry Andric         errc::invalid_argument,
142881ad6265SDimitry Andric         "multiple input files cannot be used in combination with -o");
142981ad6265SDimitry Andric 
143081ad6265SDimitry Andric   ConfigManager ConfigMgr;
143181ad6265SDimitry Andric   CommonConfig &Config = ConfigMgr.Common;
143281ad6265SDimitry Andric   ELFConfig &ELFConfig = ConfigMgr.ELF;
143381ad6265SDimitry Andric   MachOConfig &MachOConfig = ConfigMgr.MachO;
143481ad6265SDimitry Andric 
143581ad6265SDimitry Andric   if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
143681ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
143781ad6265SDimitry Andric                              "--regex and --wildcard are incompatible");
143881ad6265SDimitry Andric   MatchStyle SectionMatchStyle =
143981ad6265SDimitry Andric       InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
144081ad6265SDimitry Andric   MatchStyle SymbolMatchStyle
144181ad6265SDimitry Andric       = InputArgs.hasArg(STRIP_regex)    ? MatchStyle::Regex
144281ad6265SDimitry Andric       : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard
144381ad6265SDimitry Andric                                          : MatchStyle::Literal;
144481ad6265SDimitry Andric   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
144581ad6265SDimitry Andric   Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
144681ad6265SDimitry Andric 
144781ad6265SDimitry Andric   if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals))
144881ad6265SDimitry Andric     Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all)
144981ad6265SDimitry Andric                              ? DiscardType::All
145081ad6265SDimitry Andric                              : DiscardType::Locals;
145181ad6265SDimitry Andric   Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
145281ad6265SDimitry Andric   Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
145381ad6265SDimitry Andric   if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
145481ad6265SDimitry Andric     Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
145581ad6265SDimitry Andric   Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
145681ad6265SDimitry Andric   MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
145781ad6265SDimitry Andric   Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
145881ad6265SDimitry Andric   ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
145981ad6265SDimitry Andric   MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
146081ad6265SDimitry Andric 
1461bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(STRIP_keep_section))
146281ad6265SDimitry Andric     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
146381ad6265SDimitry Andric             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
146481ad6265SDimitry Andric       return std::move(E);
146581ad6265SDimitry Andric 
1466bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(STRIP_remove_section))
146781ad6265SDimitry Andric     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
146881ad6265SDimitry Andric             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
146981ad6265SDimitry Andric       return std::move(E);
147081ad6265SDimitry Andric 
1471bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol))
147281ad6265SDimitry Andric     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
147381ad6265SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
147481ad6265SDimitry Andric       return std::move(E);
147581ad6265SDimitry Andric 
1476bdd1243dSDimitry Andric   for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol))
147781ad6265SDimitry Andric     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
147881ad6265SDimitry Andric             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
147981ad6265SDimitry Andric       return std::move(E);
148081ad6265SDimitry Andric 
148181ad6265SDimitry Andric   if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
148281ad6265SDimitry Andric       !Config.OnlyKeepDebug && !Config.StripUnneeded &&
148381ad6265SDimitry Andric       Config.DiscardMode == DiscardType::None && !Config.StripAllGNU &&
148481ad6265SDimitry Andric       Config.SymbolsToRemove.empty())
148581ad6265SDimitry Andric     Config.StripAll = true;
148681ad6265SDimitry Andric 
148781ad6265SDimitry Andric   if (Config.DiscardMode == DiscardType::All) {
148881ad6265SDimitry Andric     Config.StripDebug = true;
148981ad6265SDimitry Andric     ELFConfig.KeepFileSymbols = true;
149081ad6265SDimitry Andric   }
149181ad6265SDimitry Andric 
149281ad6265SDimitry Andric   Config.DeterministicArchives =
149381ad6265SDimitry Andric       InputArgs.hasFlag(STRIP_enable_deterministic_archives,
149481ad6265SDimitry Andric                         STRIP_disable_deterministic_archives, /*default=*/true);
149581ad6265SDimitry Andric 
149681ad6265SDimitry Andric   Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
149781ad6265SDimitry Andric   Config.InputFormat = FileFormat::Unspecified;
149881ad6265SDimitry Andric   Config.OutputFormat = FileFormat::Unspecified;
149981ad6265SDimitry Andric 
150081ad6265SDimitry Andric   DriverConfig DC;
150181ad6265SDimitry Andric   if (Positional.size() == 1) {
150281ad6265SDimitry Andric     Config.InputFilename = Positional[0];
150381ad6265SDimitry Andric     Config.OutputFilename =
150481ad6265SDimitry Andric         InputArgs.getLastArgValue(STRIP_output, Positional[0]);
150581ad6265SDimitry Andric     DC.CopyConfigs.push_back(std::move(ConfigMgr));
150681ad6265SDimitry Andric   } else {
150781ad6265SDimitry Andric     StringMap<unsigned> InputFiles;
150881ad6265SDimitry Andric     for (StringRef Filename : Positional) {
150981ad6265SDimitry Andric       if (InputFiles[Filename]++ == 1) {
151081ad6265SDimitry Andric         if (Filename == "-")
151181ad6265SDimitry Andric           return createStringError(
151281ad6265SDimitry Andric               errc::invalid_argument,
151381ad6265SDimitry Andric               "cannot specify '-' as an input file more than once");
151481ad6265SDimitry Andric         if (Error E = ErrorCallback(createStringError(
151581ad6265SDimitry Andric                 errc::invalid_argument, "'%s' was already specified",
151681ad6265SDimitry Andric                 Filename.str().c_str())))
151781ad6265SDimitry Andric           return std::move(E);
151881ad6265SDimitry Andric       }
151981ad6265SDimitry Andric       Config.InputFilename = Filename;
152081ad6265SDimitry Andric       Config.OutputFilename = Filename;
152181ad6265SDimitry Andric       DC.CopyConfigs.push_back(ConfigMgr);
152281ad6265SDimitry Andric     }
152381ad6265SDimitry Andric   }
152481ad6265SDimitry Andric 
152581ad6265SDimitry Andric   if (Config.PreserveDates && (is_contained(Positional, "-") ||
152681ad6265SDimitry Andric                                InputArgs.getLastArgValue(STRIP_output) == "-"))
152781ad6265SDimitry Andric     return createStringError(errc::invalid_argument,
152881ad6265SDimitry Andric                              "--preserve-dates requires a file");
152981ad6265SDimitry Andric 
153081ad6265SDimitry Andric   return std::move(DC);
153181ad6265SDimitry Andric }
1532