xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp (revision 56727255ad47072ec2cc81b4ae728a099697b0e4)
1 //===- ObjcopyOptions.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ObjcopyOptions.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/BinaryFormat/COFF.h"
14 #include "llvm/ObjCopy/CommonConfig.h"
15 #include "llvm/ObjCopy/ConfigManager.h"
16 #include "llvm/ObjCopy/MachO/MachOConfig.h"
17 #include "llvm/Option/Arg.h"
18 #include "llvm/Option/ArgList.h"
19 #include "llvm/Support/CRC.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/Compression.h"
22 #include "llvm/Support/Errc.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 
26 using namespace llvm;
27 using namespace llvm::objcopy;
28 using namespace llvm::opt;
29 
30 namespace {
31 enum ObjcopyID {
32   OBJCOPY_INVALID = 0, // This is not an option ID.
33 #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
34 #include "ObjcopyOpts.inc"
35 #undef OPTION
36 };
37 
38 namespace objcopy_opt {
39 #define PREFIX(NAME, VALUE)                                                    \
40   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
41   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
42                                                 std::size(NAME##_init) - 1);
43 #include "ObjcopyOpts.inc"
44 #undef PREFIX
45 
46 static constexpr opt::OptTable::Info ObjcopyInfoTable[] = {
47 #define OPTION(...)                                                            \
48   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
49 #include "ObjcopyOpts.inc"
50 #undef OPTION
51 };
52 } // namespace objcopy_opt
53 
54 class ObjcopyOptTable : public opt::GenericOptTable {
55 public:
56   ObjcopyOptTable() : opt::GenericOptTable(objcopy_opt::ObjcopyInfoTable) {
57     setGroupedShortOptions(true);
58   }
59 };
60 
61 enum InstallNameToolID {
62   INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
63 #define OPTION(...)                                                            \
64   LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
65 #include "InstallNameToolOpts.inc"
66 #undef OPTION
67 };
68 
69 namespace install_name_tool {
70 
71 #define PREFIX(NAME, VALUE)                                                    \
72   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
73   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
74                                                 std::size(NAME##_init) - 1);
75 #include "InstallNameToolOpts.inc"
76 #undef PREFIX
77 
78 static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = {
79 #define OPTION(...)                                                            \
80   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
81 #include "InstallNameToolOpts.inc"
82 #undef OPTION
83 };
84 } // namespace install_name_tool
85 
86 class InstallNameToolOptTable : public opt::GenericOptTable {
87 public:
88   InstallNameToolOptTable()
89       : GenericOptTable(install_name_tool::InstallNameToolInfoTable) {}
90 };
91 
92 enum BitcodeStripID {
93   BITCODE_STRIP_INVALID = 0, // This is not an option ID.
94 #define OPTION(...)                                                            \
95   LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
96 #include "BitcodeStripOpts.inc"
97 #undef OPTION
98 };
99 
100 namespace bitcode_strip {
101 
102 #define PREFIX(NAME, VALUE)                                                    \
103   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
104   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
105                                                 std::size(NAME##_init) - 1);
106 #include "BitcodeStripOpts.inc"
107 #undef PREFIX
108 
109 static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = {
110 #define OPTION(...)                                                            \
111   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
112 #include "BitcodeStripOpts.inc"
113 #undef OPTION
114 };
115 } // namespace bitcode_strip
116 
117 class BitcodeStripOptTable : public opt::GenericOptTable {
118 public:
119   BitcodeStripOptTable()
120       : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable) {}
121 };
122 
123 enum StripID {
124   STRIP_INVALID = 0, // This is not an option ID.
125 #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
126 #include "StripOpts.inc"
127 #undef OPTION
128 };
129 
130 namespace strip {
131 #define PREFIX(NAME, VALUE)                                                    \
132   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
133   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
134                                                 std::size(NAME##_init) - 1);
135 #include "StripOpts.inc"
136 #undef PREFIX
137 
138 static constexpr opt::OptTable::Info StripInfoTable[] = {
139 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
140 #include "StripOpts.inc"
141 #undef OPTION
142 };
143 } // namespace strip
144 
145 class StripOptTable : public opt::GenericOptTable {
146 public:
147   StripOptTable() : GenericOptTable(strip::StripInfoTable) {
148     setGroupedShortOptions(true);
149   }
150 };
151 
152 } // namespace
153 
154 static SectionFlag parseSectionRenameFlag(StringRef SectionName) {
155   return llvm::StringSwitch<SectionFlag>(SectionName)
156       .CaseLower("alloc", SectionFlag::SecAlloc)
157       .CaseLower("load", SectionFlag::SecLoad)
158       .CaseLower("noload", SectionFlag::SecNoload)
159       .CaseLower("readonly", SectionFlag::SecReadonly)
160       .CaseLower("debug", SectionFlag::SecDebug)
161       .CaseLower("code", SectionFlag::SecCode)
162       .CaseLower("data", SectionFlag::SecData)
163       .CaseLower("rom", SectionFlag::SecRom)
164       .CaseLower("merge", SectionFlag::SecMerge)
165       .CaseLower("strings", SectionFlag::SecStrings)
166       .CaseLower("contents", SectionFlag::SecContents)
167       .CaseLower("share", SectionFlag::SecShare)
168       .CaseLower("exclude", SectionFlag::SecExclude)
169       .CaseLower("large", SectionFlag::SecLarge)
170       .Default(SectionFlag::SecNone);
171 }
172 
173 static Expected<SectionFlag>
174 parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
175   SectionFlag ParsedFlags = SectionFlag::SecNone;
176   for (StringRef Flag : SectionFlags) {
177     SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
178     if (ParsedFlag == SectionFlag::SecNone)
179       return createStringError(
180           errc::invalid_argument,
181           "unrecognized section flag '%s'. Flags supported for GNU "
182           "compatibility: alloc, load, noload, readonly, exclude, debug, "
183           "code, data, rom, share, contents, merge, strings, large",
184           Flag.str().c_str());
185     ParsedFlags |= ParsedFlag;
186   }
187 
188   return ParsedFlags;
189 }
190 
191 static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {
192   if (!FlagValue.contains('='))
193     return createStringError(errc::invalid_argument,
194                              "bad format for --rename-section: missing '='");
195 
196   // Initial split: ".foo" = ".bar,f1,f2,..."
197   auto Old2New = FlagValue.split('=');
198   SectionRename SR;
199   SR.OriginalName = Old2New.first;
200 
201   // Flags split: ".bar" "f1" "f2" ...
202   SmallVector<StringRef, 6> NameAndFlags;
203   Old2New.second.split(NameAndFlags, ',');
204   SR.NewName = NameAndFlags[0];
205 
206   if (NameAndFlags.size() > 1) {
207     Expected<SectionFlag> ParsedFlagSet =
208         parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front());
209     if (!ParsedFlagSet)
210       return ParsedFlagSet.takeError();
211     SR.NewFlags = *ParsedFlagSet;
212   }
213 
214   return SR;
215 }
216 
217 static Expected<std::pair<StringRef, uint64_t>>
218 parseSetSectionAttribute(StringRef Option, StringRef FlagValue) {
219   if (!FlagValue.contains('='))
220     return make_error<StringError>("bad format for " + Option + ": missing '='",
221                                    errc::invalid_argument);
222   auto Split = StringRef(FlagValue).split('=');
223   if (Split.first.empty())
224     return make_error<StringError>("bad format for " + Option +
225                                        ": missing section name",
226                                    errc::invalid_argument);
227   uint64_t Value;
228   if (Split.second.getAsInteger(0, Value))
229     return make_error<StringError>("invalid value for " + Option + ": '" +
230                                        Split.second + "'",
231                                    errc::invalid_argument);
232   return std::make_pair(Split.first, Value);
233 }
234 
235 static Expected<SectionFlagsUpdate>
236 parseSetSectionFlagValue(StringRef FlagValue) {
237   if (!StringRef(FlagValue).contains('='))
238     return createStringError(errc::invalid_argument,
239                              "bad format for --set-section-flags: missing '='");
240 
241   // Initial split: ".foo" = "f1,f2,..."
242   auto Section2Flags = StringRef(FlagValue).split('=');
243   SectionFlagsUpdate SFU;
244   SFU.Name = Section2Flags.first;
245 
246   // Flags split: "f1" "f2" ...
247   SmallVector<StringRef, 6> SectionFlags;
248   Section2Flags.second.split(SectionFlags, ',');
249   Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags);
250   if (!ParsedFlagSet)
251     return ParsedFlagSet.takeError();
252   SFU.NewFlags = *ParsedFlagSet;
253 
254   return SFU;
255 }
256 
257 namespace {
258 struct TargetInfo {
259   FileFormat Format;
260   MachineInfo Machine;
261 };
262 } // namespace
263 
264 // FIXME: consolidate with the bfd parsing used by lld.
265 static const StringMap<MachineInfo> TargetMap{
266     // Name, {EMachine, 64bit, LittleEndian}
267     // x86
268     {"elf32-i386", {ELF::EM_386, false, true}},
269     {"elf32-x86-64", {ELF::EM_X86_64, false, true}},
270     {"elf64-x86-64", {ELF::EM_X86_64, true, true}},
271     // Intel MCU
272     {"elf32-iamcu", {ELF::EM_IAMCU, false, true}},
273     // ARM
274     {"elf32-littlearm", {ELF::EM_ARM, false, true}},
275     // ARM AArch64
276     {"elf64-aarch64", {ELF::EM_AARCH64, true, true}},
277     {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}},
278     // RISC-V
279     {"elf32-littleriscv", {ELF::EM_RISCV, false, true}},
280     {"elf64-littleriscv", {ELF::EM_RISCV, true, true}},
281     // PowerPC
282     {"elf32-powerpc", {ELF::EM_PPC, false, false}},
283     {"elf32-powerpcle", {ELF::EM_PPC, false, true}},
284     {"elf64-powerpc", {ELF::EM_PPC64, true, false}},
285     {"elf64-powerpcle", {ELF::EM_PPC64, true, true}},
286     // MIPS
287     {"elf32-bigmips", {ELF::EM_MIPS, false, false}},
288     {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}},
289     {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}},
290     {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}},
291     {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}},
292     {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}},
293     {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}},
294     // SPARC
295     {"elf32-sparc", {ELF::EM_SPARC, false, false}},
296     {"elf32-sparcel", {ELF::EM_SPARC, false, true}},
297     // Hexagon
298     {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}},
299     // LoongArch
300     {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}},
301     {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}},
302     // SystemZ
303     {"elf64-s390", {ELF::EM_S390, true, false}},
304 };
305 
306 static Expected<TargetInfo>
307 getOutputTargetInfoByTargetName(StringRef TargetName) {
308   StringRef OriginalTargetName = TargetName;
309   bool IsFreeBSD = TargetName.consume_back("-freebsd");
310   auto Iter = TargetMap.find(TargetName);
311   if (Iter == std::end(TargetMap))
312     return createStringError(errc::invalid_argument,
313                              "invalid output format: '%s'",
314                              OriginalTargetName.str().c_str());
315   MachineInfo MI = Iter->getValue();
316   if (IsFreeBSD)
317     MI.OSABI = ELF::ELFOSABI_FREEBSD;
318 
319   FileFormat Format;
320   if (TargetName.starts_with("elf"))
321     Format = FileFormat::ELF;
322   else
323     // This should never happen because `TargetName` is valid (it certainly
324     // exists in the TargetMap).
325     llvm_unreachable("unknown target prefix");
326 
327   return {TargetInfo{Format, MI}};
328 }
329 
330 static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
331                                 StringRef Filename, MatchStyle MS,
332                                 function_ref<Error(Error)> ErrorCallback) {
333   StringSaver Saver(Alloc);
334   SmallVector<StringRef, 16> Lines;
335   auto BufOrErr = MemoryBuffer::getFile(Filename);
336   if (!BufOrErr)
337     return createFileError(Filename, BufOrErr.getError());
338 
339   BufOrErr.get()->getBuffer().split(Lines, '\n');
340   for (StringRef Line : Lines) {
341     // Ignore everything after '#', trim whitespace, and only add the symbol if
342     // it's not empty.
343     auto TrimmedLine = Line.split('#').first.trim();
344     if (!TrimmedLine.empty())
345       if (Error E = Symbols.addMatcher(NameOrPattern::create(
346               Saver.save(TrimmedLine), MS, ErrorCallback)))
347         return E;
348   }
349 
350   return Error::success();
351 }
352 
353 static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
354                                         BumpPtrAllocator &Alloc,
355                                         StringRef Filename) {
356   StringSaver Saver(Alloc);
357   SmallVector<StringRef, 16> Lines;
358   auto BufOrErr = MemoryBuffer::getFile(Filename);
359   if (!BufOrErr)
360     return createFileError(Filename, BufOrErr.getError());
361 
362   BufOrErr.get()->getBuffer().split(Lines, '\n');
363   size_t NumLines = Lines.size();
364   for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) {
365     StringRef TrimmedLine = Lines[LineNo].split('#').first.trim();
366     if (TrimmedLine.empty())
367       continue;
368 
369     std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' ');
370     StringRef NewName = Pair.second.trim();
371     if (NewName.empty())
372       return createStringError(errc::invalid_argument,
373                                "%s:%zu: missing new symbol name",
374                                Filename.str().c_str(), LineNo + 1);
375     SymbolsToRename.insert({Pair.first, NewName});
376   }
377   return Error::success();
378 }
379 
380 template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
381   T Result;
382   if (Val.getAsInteger(0, Result))
383     return errc::invalid_argument;
384   return Result;
385 }
386 
387 namespace {
388 
389 enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip };
390 
391 } // anonymous namespace
392 
393 static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
394                       ToolType Tool) {
395   StringRef HelpText, ToolName;
396   switch (Tool) {
397   case ToolType::Objcopy:
398     ToolName = "llvm-objcopy";
399     HelpText = " [options] input [output]";
400     break;
401   case ToolType::Strip:
402     ToolName = "llvm-strip";
403     HelpText = " [options] inputs...";
404     break;
405   case ToolType::InstallNameTool:
406     ToolName = "llvm-install-name-tool";
407     HelpText = " [options] input";
408     break;
409   case ToolType::BitcodeStrip:
410     ToolName = "llvm-bitcode-strip";
411     HelpText = " [options] input";
412     break;
413   }
414   OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
415                      (ToolName + " tool").str().c_str());
416   // TODO: Replace this with libOption call once it adds extrahelp support.
417   // The CommandLine library has a cl::extrahelp class to support this,
418   // but libOption does not have that yet.
419   OS << "\nPass @FILE as argument to read options from FILE.\n";
420 }
421 
422 static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
423   // Parse value given with --add-symbol option and create the
424   // new symbol if possible. The value format for --add-symbol is:
425   //
426   // <name>=[<section>:]<value>[,<flags>]
427   //
428   // where:
429   // <name> - symbol name, can be empty string
430   // <section> - optional section name. If not given ABS symbol is created
431   // <value> - symbol value, can be decimal or hexadecimal number prefixed
432   //           with 0x.
433   // <flags> - optional flags affecting symbol type, binding or visibility.
434   NewSymbolInfo SI;
435   StringRef Value;
436   std::tie(SI.SymbolName, Value) = FlagValue.split('=');
437   if (Value.empty())
438     return createStringError(
439         errc::invalid_argument,
440         "bad format for --add-symbol, missing '=' after '%s'",
441         SI.SymbolName.str().c_str());
442 
443   if (Value.contains(':')) {
444     std::tie(SI.SectionName, Value) = Value.split(':');
445     if (SI.SectionName.empty() || Value.empty())
446       return createStringError(
447           errc::invalid_argument,
448           "bad format for --add-symbol, missing section name or symbol value");
449   }
450 
451   SmallVector<StringRef, 6> Flags;
452   Value.split(Flags, ',');
453   if (Flags[0].getAsInteger(0, SI.Value))
454     return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
455                              Flags[0].str().c_str());
456 
457   using Functor = std::function<void()>;
458   SmallVector<StringRef, 6> UnsupportedFlags;
459   for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
460     static_cast<Functor>(
461         StringSwitch<Functor>(Flags[I])
462             .CaseLower("global",
463                        [&] { SI.Flags.push_back(SymbolFlag::Global); })
464             .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); })
465             .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); })
466             .CaseLower("default",
467                        [&] { SI.Flags.push_back(SymbolFlag::Default); })
468             .CaseLower("hidden",
469                        [&] { SI.Flags.push_back(SymbolFlag::Hidden); })
470             .CaseLower("protected",
471                        [&] { SI.Flags.push_back(SymbolFlag::Protected); })
472             .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); })
473             .CaseLower("section",
474                        [&] { SI.Flags.push_back(SymbolFlag::Section); })
475             .CaseLower("object",
476                        [&] { SI.Flags.push_back(SymbolFlag::Object); })
477             .CaseLower("function",
478                        [&] { SI.Flags.push_back(SymbolFlag::Function); })
479             .CaseLower(
480                 "indirect-function",
481                 [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); })
482             .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); })
483             .CaseLower("constructor",
484                        [&] { SI.Flags.push_back(SymbolFlag::Constructor); })
485             .CaseLower("warning",
486                        [&] { SI.Flags.push_back(SymbolFlag::Warning); })
487             .CaseLower("indirect",
488                        [&] { SI.Flags.push_back(SymbolFlag::Indirect); })
489             .CaseLower("synthetic",
490                        [&] { SI.Flags.push_back(SymbolFlag::Synthetic); })
491             .CaseLower("unique-object",
492                        [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); })
493             .StartsWithLower("before=",
494                              [&] {
495                                StringRef SymNamePart =
496                                    Flags[I].split('=').second;
497 
498                                if (!SymNamePart.empty())
499                                  SI.BeforeSyms.push_back(SymNamePart);
500                              })
501             .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
502   if (!UnsupportedFlags.empty())
503     return createStringError(errc::invalid_argument,
504                              "unsupported flag%s for --add-symbol: '%s'",
505                              UnsupportedFlags.size() > 1 ? "s" : "",
506                              join(UnsupportedFlags, "', '").c_str());
507 
508   return SI;
509 }
510 
511 // Parse input option \p ArgValue and load section data. This function
512 // extracts section name and name of the file keeping section data from
513 // ArgValue, loads data from the file, and stores section name and data
514 // into the vector of new sections \p NewSections.
515 static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
516                                 std::vector<NewSectionInfo> &NewSections) {
517   if (!ArgValue.contains('='))
518     return createStringError(errc::invalid_argument,
519                              "bad format for " + OptionName + ": missing '='");
520 
521   std::pair<StringRef, StringRef> SecPair = ArgValue.split("=");
522   if (SecPair.second.empty())
523     return createStringError(errc::invalid_argument, "bad format for " +
524                                                          OptionName +
525                                                          ": missing file name");
526 
527   ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
528       MemoryBuffer::getFile(SecPair.second);
529   if (!BufOrErr)
530     return createFileError(SecPair.second,
531                            errorCodeToError(BufOrErr.getError()));
532 
533   NewSections.push_back({SecPair.first, std::move(*BufOrErr)});
534   return Error::success();
535 }
536 
537 // parseObjcopyOptions returns the config and sets the input arguments. If a
538 // help flag is set then parseObjcopyOptions will print the help messege and
539 // exit.
540 Expected<DriverConfig>
541 objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
542                              function_ref<Error(Error)> ErrorCallback) {
543   DriverConfig DC;
544   ObjcopyOptTable T;
545 
546   const char *const *DashDash =
547       llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
548   ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
549   if (DashDash != RawArgsArr.end())
550     DashDash = std::next(DashDash);
551 
552   unsigned MissingArgumentIndex, MissingArgumentCount;
553   llvm::opt::InputArgList InputArgs =
554       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
555 
556   if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
557     printHelp(T, errs(), ToolType::Objcopy);
558     exit(1);
559   }
560 
561   if (InputArgs.hasArg(OBJCOPY_help)) {
562     printHelp(T, outs(), ToolType::Objcopy);
563     exit(0);
564   }
565 
566   if (InputArgs.hasArg(OBJCOPY_version)) {
567     outs() << "llvm-objcopy, compatible with GNU objcopy\n";
568     cl::PrintVersionMessage();
569     exit(0);
570   }
571 
572   SmallVector<const char *, 2> Positional;
573 
574   for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
575     return createStringError(errc::invalid_argument, "unknown argument '%s'",
576                              Arg->getAsString(InputArgs).c_str());
577 
578   for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
579     Positional.push_back(Arg->getValue());
580   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
581 
582   if (Positional.empty())
583     return createStringError(errc::invalid_argument, "no input file specified");
584 
585   if (Positional.size() > 2)
586     return createStringError(errc::invalid_argument,
587                              "too many positional arguments");
588 
589   ConfigManager ConfigMgr;
590   CommonConfig &Config = ConfigMgr.Common;
591   COFFConfig &COFFConfig = ConfigMgr.COFF;
592   ELFConfig &ELFConfig = ConfigMgr.ELF;
593   MachOConfig &MachOConfig = ConfigMgr.MachO;
594   Config.InputFilename = Positional[0];
595   Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
596   if (InputArgs.hasArg(OBJCOPY_target) &&
597       (InputArgs.hasArg(OBJCOPY_input_target) ||
598        InputArgs.hasArg(OBJCOPY_output_target)))
599     return createStringError(
600         errc::invalid_argument,
601         "--target cannot be used with --input-target or --output-target");
602 
603   if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
604     return createStringError(errc::invalid_argument,
605                              "--regex and --wildcard are incompatible");
606 
607   MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
608                                      ? MatchStyle::Regex
609                                      : MatchStyle::Wildcard;
610   MatchStyle SymbolMatchStyle
611       = InputArgs.hasArg(OBJCOPY_regex)    ? MatchStyle::Regex
612       : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard
613                                            : MatchStyle::Literal;
614   StringRef InputFormat, OutputFormat;
615   if (InputArgs.hasArg(OBJCOPY_target)) {
616     InputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
617     OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
618   } else {
619     InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
620     OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
621   }
622 
623   // FIXME:  Currently, we ignore the target for non-binary/ihex formats
624   // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the
625   // format by llvm::object::createBinary regardless of the option value.
626   Config.InputFormat = StringSwitch<FileFormat>(InputFormat)
627                            .Case("binary", FileFormat::Binary)
628                            .Case("ihex", FileFormat::IHex)
629                            .Default(FileFormat::Unspecified);
630 
631   if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) {
632     const uint8_t Invalid = 0xff;
633     StringRef VisibilityStr =
634         InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
635 
636     ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr)
637                                         .Case("default", ELF::STV_DEFAULT)
638                                         .Case("hidden", ELF::STV_HIDDEN)
639                                         .Case("internal", ELF::STV_INTERNAL)
640                                         .Case("protected", ELF::STV_PROTECTED)
641                                         .Default(Invalid);
642 
643     if (ELFConfig.NewSymbolVisibility == Invalid)
644       return createStringError(errc::invalid_argument,
645                                "'%s' is not a valid symbol visibility",
646                                VisibilityStr.str().c_str());
647   }
648 
649   for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) {
650     StringRef Subsystem, Version;
651     std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':');
652     COFFConfig.Subsystem =
653         StringSwitch<unsigned>(Subsystem.lower())
654             .Case("boot_application",
655                   COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
656             .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
657             .Case("efi_application", COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION)
658             .Case("efi_boot_service_driver",
659                   COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
660             .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM)
661             .Case("efi_runtime_driver",
662                   COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
663             .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE)
664             .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI)
665             .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
666             .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN);
667     if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN)
668       return createStringError(errc::invalid_argument,
669                                "'%s' is not a valid subsystem",
670                                Subsystem.str().c_str());
671     if (!Version.empty()) {
672       StringRef Major, Minor;
673       std::tie(Major, Minor) = Version.split('.');
674       unsigned Number;
675       if (Major.getAsInteger(10, Number))
676         return createStringError(errc::invalid_argument,
677                                  "'%s' is not a valid subsystem major version",
678                                  Major.str().c_str());
679       COFFConfig.MajorSubsystemVersion = Number;
680       Number = 0;
681       if (!Minor.empty() && Minor.getAsInteger(10, Number))
682         return createStringError(errc::invalid_argument,
683                                  "'%s' is not a valid subsystem minor version",
684                                  Minor.str().c_str());
685       COFFConfig.MinorSubsystemVersion = Number;
686     }
687   }
688 
689   Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
690                             .Case("binary", FileFormat::Binary)
691                             .Case("ihex", FileFormat::IHex)
692                             .Default(FileFormat::Unspecified);
693   if (Config.OutputFormat == FileFormat::Unspecified) {
694     if (OutputFormat.empty()) {
695       Config.OutputFormat = Config.InputFormat;
696     } else {
697       Expected<TargetInfo> Target =
698           getOutputTargetInfoByTargetName(OutputFormat);
699       if (!Target)
700         return Target.takeError();
701       Config.OutputFormat = Target->Format;
702       Config.OutputArch = Target->Machine;
703     }
704   }
705 
706   if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) {
707     Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue())
708                                  .Case("zlib", DebugCompressionType::Zlib)
709                                  .Case("zstd", DebugCompressionType::Zstd)
710                                  .Default(DebugCompressionType::None);
711     if (Config.CompressionType == DebugCompressionType::None) {
712       return createStringError(
713           errc::invalid_argument,
714           "invalid or unsupported --compress-debug-sections format: %s",
715           A->getValue());
716     }
717     if (const char *Reason = compression::getReasonIfUnsupported(
718             compression::formatFor(Config.CompressionType)))
719       return createStringError(errc::invalid_argument, Reason);
720   }
721 
722   Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
723   // The gnu_debuglink's target is expected to not change or else its CRC would
724   // become invalidated and get rejected. We can avoid recalculating the
725   // checksum for every target file inside an archive by precomputing the CRC
726   // here. This prevents a significant amount of I/O.
727   if (!Config.AddGnuDebugLink.empty()) {
728     auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink);
729     if (!DebugOrErr)
730       return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());
731     auto Debug = std::move(*DebugOrErr);
732     Config.GnuDebugLinkCRC32 =
733         llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
734   }
735   Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
736   Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
737   Config.AllocSectionsPrefix =
738       InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
739   if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
740     Config.ExtractPartition = Arg->getValue();
741 
742   if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) {
743     if (Config.OutputFormat != FileFormat::Binary)
744       return createStringError(
745           errc::invalid_argument,
746           "'--gap-fill' is only supported for binary output");
747     ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue());
748     if (!Val)
749       return createStringError(Val.getError(), "--gap-fill: bad number: %s",
750                                A->getValue());
751     uint8_t ByteVal = Val.get();
752     if (ByteVal != Val.get())
753       return createStringError(std::errc::value_too_large,
754                                "gap-fill value %s is out of range (0 to 0xff)",
755                                A->getValue());
756     Config.GapFill = ByteVal;
757   }
758 
759   if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) {
760     if (Config.OutputFormat != FileFormat::Binary)
761       return createStringError(
762           errc::invalid_argument,
763           "'--pad-to' is only supported for binary output");
764     ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue());
765     if (!Addr)
766       return createStringError(Addr.getError(), "--pad-to: bad number: %s",
767                                A->getValue());
768     Config.PadTo = *Addr;
769   }
770 
771   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
772     if (!StringRef(Arg->getValue()).contains('='))
773       return createStringError(errc::invalid_argument,
774                                "bad format for --redefine-sym");
775     auto Old2New = StringRef(Arg->getValue()).split('=');
776     if (!Config.SymbolsToRename.insert(Old2New).second)
777       return createStringError(errc::invalid_argument,
778                                "multiple redefinition of symbol '%s'",
779                                Old2New.first.str().c_str());
780   }
781 
782   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
783     if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
784                                              Arg->getValue()))
785       return std::move(E);
786 
787   for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
788     Expected<SectionRename> SR =
789         parseRenameSectionValue(StringRef(Arg->getValue()));
790     if (!SR)
791       return SR.takeError();
792     if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
793       return createStringError(errc::invalid_argument,
794                                "multiple renames of section '%s'",
795                                SR->OriginalName.str().c_str());
796   }
797   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
798     Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
799         parseSetSectionAttribute("--set-section-alignment", Arg->getValue());
800     if (!NameAndAlign)
801       return NameAndAlign.takeError();
802     Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
803   }
804   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
805     Expected<SectionFlagsUpdate> SFU =
806         parseSetSectionFlagValue(Arg->getValue());
807     if (!SFU)
808       return SFU.takeError();
809     if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
810       return createStringError(
811           errc::invalid_argument,
812           "--set-section-flags set multiple times for section '%s'",
813           SFU->Name.str().c_str());
814   }
815   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) {
816     Expected<std::pair<StringRef, uint64_t>> NameAndType =
817         parseSetSectionAttribute("--set-section-type", Arg->getValue());
818     if (!NameAndType)
819       return NameAndType.takeError();
820     Config.SetSectionType[NameAndType->first] = NameAndType->second;
821   }
822   // Prohibit combinations of --set-section-{flags,type} when the section name
823   // is used as the destination of a --rename-section.
824   for (const auto &E : Config.SectionsToRename) {
825     const SectionRename &SR = E.second;
826     auto Err = [&](const char *Option) {
827       return createStringError(
828           errc::invalid_argument,
829           "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option,
830           SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
831           SR.NewName.str().c_str());
832     };
833     if (Config.SetSectionFlags.count(SR.NewName))
834       return Err("flags");
835     if (Config.SetSectionType.count(SR.NewName))
836       return Err("type");
837   }
838 
839   for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section))
840     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
841             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
842       return std::move(E);
843   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section))
844     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
845             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
846       return std::move(E);
847   for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section))
848     if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
849             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
850       return std::move(E);
851   for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) {
852     if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section",
853                                        Config.AddSection))
854       return std::move(Err);
855   }
856   for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) {
857     if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section",
858                                        Config.UpdateSection))
859       return std::move(Err);
860   }
861   for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
862     StringRef Value(Arg->getValue());
863     if (Value.split('=').second.empty())
864       return createStringError(
865           errc::invalid_argument,
866           "bad format for --dump-section, expected section=file");
867     Config.DumpSection.push_back(Value);
868   }
869   Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
870   Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
871   Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
872   Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
873   Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
874   Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
875   Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
876   Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
877   Config.ExtractMainPartition =
878       InputArgs.hasArg(OBJCOPY_extract_main_partition);
879   ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
880   Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
881   if (auto *Arg =
882           InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
883     Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all)
884                              ? DiscardType::All
885                              : DiscardType::Locals;
886   }
887   Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
888   ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
889   MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
890   Config.DecompressDebugSections =
891       InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
892   if (Config.DiscardMode == DiscardType::All) {
893     Config.StripDebug = true;
894     ELFConfig.KeepFileSymbols = true;
895   }
896   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
897     if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
898             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
899       return std::move(E);
900   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
901     if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
902                                      Arg->getValue(), SymbolMatchStyle,
903                                      ErrorCallback))
904       return std::move(E);
905   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
906     if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
907             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
908       return std::move(E);
909   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
910     if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
911                                      Arg->getValue(), SymbolMatchStyle,
912                                      ErrorCallback))
913       return std::move(E);
914   for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
915     if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
916             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
917       return std::move(E);
918   for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
919     if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
920                                      Arg->getValue(), SymbolMatchStyle,
921                                      ErrorCallback))
922       return std::move(E);
923   for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
924     if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
925             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
926       return std::move(E);
927   for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
928     if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
929                                      Arg->getValue(), SymbolMatchStyle,
930                                      ErrorCallback))
931       return std::move(E);
932   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
933     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
934             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
935       return std::move(E);
936   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
937     if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
938                                      Arg->getValue(), SymbolMatchStyle,
939                                      ErrorCallback))
940       return std::move(E);
941   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
942     if (Error E =
943             Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
944                 Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
945       return std::move(E);
946   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
947     if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
948                                      Arg->getValue(), SymbolMatchStyle,
949                                      ErrorCallback))
950       return std::move(E);
951   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
952     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
953             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
954       return std::move(E);
955   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
956     if (Error E =
957             addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
958                                SymbolMatchStyle, ErrorCallback))
959       return std::move(E);
960   for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
961     Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
962     if (!SymInfo)
963       return SymInfo.takeError();
964 
965     Config.SymbolsToAdd.push_back(*SymInfo);
966   }
967 
968   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
969 
970   Config.DeterministicArchives = InputArgs.hasFlag(
971       OBJCOPY_enable_deterministic_archives,
972       OBJCOPY_disable_deterministic_archives, /*default=*/true);
973 
974   Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
975 
976   if (Config.PreserveDates &&
977       (Config.OutputFilename == "-" || Config.InputFilename == "-"))
978     return createStringError(errc::invalid_argument,
979                              "--preserve-dates requires a file");
980 
981   for (auto *Arg : InputArgs)
982     if (Arg->getOption().matches(OBJCOPY_set_start)) {
983       auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
984       if (!EAddr)
985         return createStringError(
986             EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
987 
988       ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
989     } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
990       auto EIncr = getAsInteger<int64_t>(Arg->getValue());
991       if (!EIncr)
992         return createStringError(EIncr.getError(),
993                                  "bad entry point increment: '%s'",
994                                  Arg->getValue());
995       auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr)
996                                       : [](uint64_t A) { return A; };
997       ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
998         return Expr(EAddr) + *EIncr;
999       };
1000     }
1001 
1002   if (Config.DecompressDebugSections &&
1003       Config.CompressionType != DebugCompressionType::None) {
1004     return createStringError(
1005         errc::invalid_argument,
1006         "cannot specify both --compress-debug-sections and "
1007         "--decompress-debug-sections");
1008   }
1009 
1010   if (Config.ExtractPartition && Config.ExtractMainPartition)
1011     return createStringError(errc::invalid_argument,
1012                              "cannot specify --extract-partition together with "
1013                              "--extract-main-partition");
1014 
1015   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1016   return std::move(DC);
1017 }
1018 
1019 // parseInstallNameToolOptions returns the config and sets the input arguments.
1020 // If a help flag is set then parseInstallNameToolOptions will print the help
1021 // messege and exit.
1022 Expected<DriverConfig>
1023 objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
1024   DriverConfig DC;
1025   ConfigManager ConfigMgr;
1026   CommonConfig &Config = ConfigMgr.Common;
1027   MachOConfig &MachOConfig = ConfigMgr.MachO;
1028   InstallNameToolOptTable T;
1029   unsigned MissingArgumentIndex, MissingArgumentCount;
1030   llvm::opt::InputArgList InputArgs =
1031       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1032 
1033   if (MissingArgumentCount)
1034     return createStringError(
1035         errc::invalid_argument,
1036         "missing argument to " +
1037             StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
1038             " option");
1039 
1040   if (InputArgs.size() == 0) {
1041     printHelp(T, errs(), ToolType::InstallNameTool);
1042     exit(1);
1043   }
1044 
1045   if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
1046     printHelp(T, outs(), ToolType::InstallNameTool);
1047     exit(0);
1048   }
1049 
1050   if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
1051     outs() << "llvm-install-name-tool, compatible with cctools "
1052               "install_name_tool\n";
1053     cl::PrintVersionMessage();
1054     exit(0);
1055   }
1056 
1057   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
1058     MachOConfig.RPathToAdd.push_back(Arg->getValue());
1059 
1060   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
1061     MachOConfig.RPathToPrepend.push_back(Arg->getValue());
1062 
1063   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
1064     StringRef RPath = Arg->getValue();
1065 
1066     // Cannot add and delete the same rpath at the same time.
1067     if (is_contained(MachOConfig.RPathToAdd, RPath))
1068       return createStringError(
1069           errc::invalid_argument,
1070           "cannot specify both -add_rpath '%s' and -delete_rpath '%s'",
1071           RPath.str().c_str(), RPath.str().c_str());
1072     if (is_contained(MachOConfig.RPathToPrepend, RPath))
1073       return createStringError(
1074           errc::invalid_argument,
1075           "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'",
1076           RPath.str().c_str(), RPath.str().c_str());
1077 
1078     MachOConfig.RPathsToRemove.insert(RPath);
1079   }
1080 
1081   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) {
1082     StringRef Old = Arg->getValue(0);
1083     StringRef New = Arg->getValue(1);
1084 
1085     auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; };
1086 
1087     // Cannot specify duplicate -rpath entries
1088     auto It1 = find_if(
1089         MachOConfig.RPathsToUpdate,
1090         [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) {
1091           return Match(OldNew.getFirst()) || Match(OldNew.getSecond());
1092         });
1093     if (It1 != MachOConfig.RPathsToUpdate.end())
1094       return createStringError(errc::invalid_argument,
1095                                "cannot specify both -rpath '" +
1096                                    It1->getFirst() + "' '" + It1->getSecond() +
1097                                    "' and -rpath '" + Old + "' '" + New + "'");
1098 
1099     // Cannot specify the same rpath under both -delete_rpath and -rpath
1100     auto It2 = find_if(MachOConfig.RPathsToRemove, Match);
1101     if (It2 != MachOConfig.RPathsToRemove.end())
1102       return createStringError(errc::invalid_argument,
1103                                "cannot specify both -delete_rpath '" + *It2 +
1104                                    "' and -rpath '" + Old + "' '" + New + "'");
1105 
1106     // Cannot specify the same rpath under both -add_rpath and -rpath
1107     auto It3 = find_if(MachOConfig.RPathToAdd, Match);
1108     if (It3 != MachOConfig.RPathToAdd.end())
1109       return createStringError(errc::invalid_argument,
1110                                "cannot specify both -add_rpath '" + *It3 +
1111                                    "' and -rpath '" + Old + "' '" + New + "'");
1112 
1113     // Cannot specify the same rpath under both -prepend_rpath and -rpath.
1114     auto It4 = find_if(MachOConfig.RPathToPrepend, Match);
1115     if (It4 != MachOConfig.RPathToPrepend.end())
1116       return createStringError(errc::invalid_argument,
1117                                "cannot specify both -prepend_rpath '" + *It4 +
1118                                    "' and -rpath '" + Old + "' '" + New + "'");
1119 
1120     MachOConfig.RPathsToUpdate.insert({Old, New});
1121   }
1122 
1123   if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) {
1124     MachOConfig.SharedLibId = Arg->getValue();
1125     if (MachOConfig.SharedLibId->empty())
1126       return createStringError(errc::invalid_argument,
1127                                "cannot specify an empty id");
1128   }
1129 
1130   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change))
1131     MachOConfig.InstallNamesToUpdate.insert(
1132         {Arg->getValue(0), Arg->getValue(1)});
1133 
1134   MachOConfig.RemoveAllRpaths =
1135       InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);
1136 
1137   SmallVector<StringRef, 2> Positional;
1138   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
1139     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1140                              Arg->getAsString(InputArgs).c_str());
1141   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
1142     Positional.push_back(Arg->getValue());
1143   if (Positional.empty())
1144     return createStringError(errc::invalid_argument, "no input file specified");
1145   if (Positional.size() > 1)
1146     return createStringError(
1147         errc::invalid_argument,
1148         "llvm-install-name-tool expects a single input file");
1149   Config.InputFilename = Positional[0];
1150   Config.OutputFilename = Positional[0];
1151 
1152   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1153   return std::move(DC);
1154 }
1155 
1156 Expected<DriverConfig>
1157 objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
1158                                   function_ref<Error(Error)> ErrorCallback) {
1159   DriverConfig DC;
1160   ConfigManager ConfigMgr;
1161   CommonConfig &Config = ConfigMgr.Common;
1162   MachOConfig &MachOConfig = ConfigMgr.MachO;
1163   BitcodeStripOptTable T;
1164   unsigned MissingArgumentIndex, MissingArgumentCount;
1165   opt::InputArgList InputArgs =
1166       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1167 
1168   if (InputArgs.size() == 0) {
1169     printHelp(T, errs(), ToolType::BitcodeStrip);
1170     exit(1);
1171   }
1172 
1173   if (InputArgs.hasArg(BITCODE_STRIP_help)) {
1174     printHelp(T, outs(), ToolType::BitcodeStrip);
1175     exit(0);
1176   }
1177 
1178   if (InputArgs.hasArg(BITCODE_STRIP_version)) {
1179     outs() << "llvm-bitcode-strip, compatible with cctools "
1180               "bitcode_strip\n";
1181     cl::PrintVersionMessage();
1182     exit(0);
1183   }
1184 
1185   for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN))
1186     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1187                              Arg->getAsString(InputArgs).c_str());
1188 
1189   SmallVector<StringRef, 2> Positional;
1190   for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
1191     Positional.push_back(Arg->getValue());
1192   if (Positional.size() > 1)
1193     return createStringError(errc::invalid_argument,
1194                              "llvm-bitcode-strip expects a single input file");
1195   assert(!Positional.empty());
1196   Config.InputFilename = Positional[0];
1197 
1198   if (!InputArgs.hasArg(BITCODE_STRIP_output)) {
1199     return createStringError(errc::invalid_argument,
1200                              "-o is a required argument");
1201   }
1202   Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output);
1203 
1204   if (!InputArgs.hasArg(BITCODE_STRIP_remove))
1205     return createStringError(errc::invalid_argument, "no action specified");
1206 
1207   // We only support -r for now, which removes all bitcode sections and
1208   // the __LLVM segment if it's now empty.
1209   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1210       "__LLVM,__asm", MatchStyle::Literal, ErrorCallback)));
1211   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1212       "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback)));
1213   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1214       "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback)));
1215   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1216       "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback)));
1217   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1218       "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback)));
1219   MachOConfig.EmptySegmentsToRemove.insert("__LLVM");
1220 
1221   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1222   return std::move(DC);
1223 }
1224 
1225 // parseStripOptions returns the config and sets the input arguments. If a
1226 // help flag is set then parseStripOptions will print the help messege and
1227 // exit.
1228 Expected<DriverConfig>
1229 objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
1230                            function_ref<Error(Error)> ErrorCallback) {
1231   const char *const *DashDash =
1232       llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
1233   ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
1234   if (DashDash != RawArgsArr.end())
1235     DashDash = std::next(DashDash);
1236 
1237   StripOptTable T;
1238   unsigned MissingArgumentIndex, MissingArgumentCount;
1239   llvm::opt::InputArgList InputArgs =
1240       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1241 
1242   if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
1243     printHelp(T, errs(), ToolType::Strip);
1244     exit(1);
1245   }
1246 
1247   if (InputArgs.hasArg(STRIP_help)) {
1248     printHelp(T, outs(), ToolType::Strip);
1249     exit(0);
1250   }
1251 
1252   if (InputArgs.hasArg(STRIP_version)) {
1253     outs() << "llvm-strip, compatible with GNU strip\n";
1254     cl::PrintVersionMessage();
1255     exit(0);
1256   }
1257 
1258   SmallVector<StringRef, 2> Positional;
1259   for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
1260     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1261                              Arg->getAsString(InputArgs).c_str());
1262   for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
1263     Positional.push_back(Arg->getValue());
1264   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
1265 
1266   if (Positional.empty())
1267     return createStringError(errc::invalid_argument, "no input file specified");
1268 
1269   if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
1270     return createStringError(
1271         errc::invalid_argument,
1272         "multiple input files cannot be used in combination with -o");
1273 
1274   ConfigManager ConfigMgr;
1275   CommonConfig &Config = ConfigMgr.Common;
1276   ELFConfig &ELFConfig = ConfigMgr.ELF;
1277   MachOConfig &MachOConfig = ConfigMgr.MachO;
1278 
1279   if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
1280     return createStringError(errc::invalid_argument,
1281                              "--regex and --wildcard are incompatible");
1282   MatchStyle SectionMatchStyle =
1283       InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
1284   MatchStyle SymbolMatchStyle
1285       = InputArgs.hasArg(STRIP_regex)    ? MatchStyle::Regex
1286       : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard
1287                                          : MatchStyle::Literal;
1288   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
1289   Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
1290 
1291   if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals))
1292     Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all)
1293                              ? DiscardType::All
1294                              : DiscardType::Locals;
1295   Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
1296   Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
1297   if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
1298     Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
1299   Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
1300   MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
1301   Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
1302   ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
1303   MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
1304 
1305   for (auto *Arg : InputArgs.filtered(STRIP_keep_section))
1306     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
1307             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1308       return std::move(E);
1309 
1310   for (auto *Arg : InputArgs.filtered(STRIP_remove_section))
1311     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
1312             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1313       return std::move(E);
1314 
1315   for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol))
1316     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
1317             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1318       return std::move(E);
1319 
1320   for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol))
1321     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
1322             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1323       return std::move(E);
1324 
1325   if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
1326       !Config.OnlyKeepDebug && !Config.StripUnneeded &&
1327       Config.DiscardMode == DiscardType::None && !Config.StripAllGNU &&
1328       Config.SymbolsToRemove.empty())
1329     Config.StripAll = true;
1330 
1331   if (Config.DiscardMode == DiscardType::All) {
1332     Config.StripDebug = true;
1333     ELFConfig.KeepFileSymbols = true;
1334   }
1335 
1336   Config.DeterministicArchives =
1337       InputArgs.hasFlag(STRIP_enable_deterministic_archives,
1338                         STRIP_disable_deterministic_archives, /*default=*/true);
1339 
1340   Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
1341   Config.InputFormat = FileFormat::Unspecified;
1342   Config.OutputFormat = FileFormat::Unspecified;
1343 
1344   DriverConfig DC;
1345   if (Positional.size() == 1) {
1346     Config.InputFilename = Positional[0];
1347     Config.OutputFilename =
1348         InputArgs.getLastArgValue(STRIP_output, Positional[0]);
1349     DC.CopyConfigs.push_back(std::move(ConfigMgr));
1350   } else {
1351     StringMap<unsigned> InputFiles;
1352     for (StringRef Filename : Positional) {
1353       if (InputFiles[Filename]++ == 1) {
1354         if (Filename == "-")
1355           return createStringError(
1356               errc::invalid_argument,
1357               "cannot specify '-' as an input file more than once");
1358         if (Error E = ErrorCallback(createStringError(
1359                 errc::invalid_argument, "'%s' was already specified",
1360                 Filename.str().c_str())))
1361           return std::move(E);
1362       }
1363       Config.InputFilename = Filename;
1364       Config.OutputFilename = Filename;
1365       DC.CopyConfigs.push_back(ConfigMgr);
1366     }
1367   }
1368 
1369   if (Config.PreserveDates && (is_contained(Positional, "-") ||
1370                                InputArgs.getLastArgValue(STRIP_output) == "-"))
1371     return createStringError(errc::invalid_argument,
1372                              "--preserve-dates requires a file");
1373 
1374   return std::move(DC);
1375 }
1376