xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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 };
303 
304 static Expected<TargetInfo>
305 getOutputTargetInfoByTargetName(StringRef TargetName) {
306   StringRef OriginalTargetName = TargetName;
307   bool IsFreeBSD = TargetName.consume_back("-freebsd");
308   auto Iter = TargetMap.find(TargetName);
309   if (Iter == std::end(TargetMap))
310     return createStringError(errc::invalid_argument,
311                              "invalid output format: '%s'",
312                              OriginalTargetName.str().c_str());
313   MachineInfo MI = Iter->getValue();
314   if (IsFreeBSD)
315     MI.OSABI = ELF::ELFOSABI_FREEBSD;
316 
317   FileFormat Format;
318   if (TargetName.starts_with("elf"))
319     Format = FileFormat::ELF;
320   else
321     // This should never happen because `TargetName` is valid (it certainly
322     // exists in the TargetMap).
323     llvm_unreachable("unknown target prefix");
324 
325   return {TargetInfo{Format, MI}};
326 }
327 
328 static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
329                                 StringRef Filename, MatchStyle MS,
330                                 function_ref<Error(Error)> ErrorCallback) {
331   StringSaver Saver(Alloc);
332   SmallVector<StringRef, 16> Lines;
333   auto BufOrErr = MemoryBuffer::getFile(Filename);
334   if (!BufOrErr)
335     return createFileError(Filename, BufOrErr.getError());
336 
337   BufOrErr.get()->getBuffer().split(Lines, '\n');
338   for (StringRef Line : Lines) {
339     // Ignore everything after '#', trim whitespace, and only add the symbol if
340     // it's not empty.
341     auto TrimmedLine = Line.split('#').first.trim();
342     if (!TrimmedLine.empty())
343       if (Error E = Symbols.addMatcher(NameOrPattern::create(
344               Saver.save(TrimmedLine), MS, ErrorCallback)))
345         return E;
346   }
347 
348   return Error::success();
349 }
350 
351 static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
352                                         BumpPtrAllocator &Alloc,
353                                         StringRef Filename) {
354   StringSaver Saver(Alloc);
355   SmallVector<StringRef, 16> Lines;
356   auto BufOrErr = MemoryBuffer::getFile(Filename);
357   if (!BufOrErr)
358     return createFileError(Filename, BufOrErr.getError());
359 
360   BufOrErr.get()->getBuffer().split(Lines, '\n');
361   size_t NumLines = Lines.size();
362   for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) {
363     StringRef TrimmedLine = Lines[LineNo].split('#').first.trim();
364     if (TrimmedLine.empty())
365       continue;
366 
367     std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' ');
368     StringRef NewName = Pair.second.trim();
369     if (NewName.empty())
370       return createStringError(errc::invalid_argument,
371                                "%s:%zu: missing new symbol name",
372                                Filename.str().c_str(), LineNo + 1);
373     SymbolsToRename.insert({Pair.first, NewName});
374   }
375   return Error::success();
376 }
377 
378 template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
379   T Result;
380   if (Val.getAsInteger(0, Result))
381     return errc::invalid_argument;
382   return Result;
383 }
384 
385 namespace {
386 
387 enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip };
388 
389 } // anonymous namespace
390 
391 static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
392                       ToolType Tool) {
393   StringRef HelpText, ToolName;
394   switch (Tool) {
395   case ToolType::Objcopy:
396     ToolName = "llvm-objcopy";
397     HelpText = " [options] input [output]";
398     break;
399   case ToolType::Strip:
400     ToolName = "llvm-strip";
401     HelpText = " [options] inputs...";
402     break;
403   case ToolType::InstallNameTool:
404     ToolName = "llvm-install-name-tool";
405     HelpText = " [options] input";
406     break;
407   case ToolType::BitcodeStrip:
408     ToolName = "llvm-bitcode-strip";
409     HelpText = " [options] input";
410     break;
411   }
412   OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
413                      (ToolName + " tool").str().c_str());
414   // TODO: Replace this with libOption call once it adds extrahelp support.
415   // The CommandLine library has a cl::extrahelp class to support this,
416   // but libOption does not have that yet.
417   OS << "\nPass @FILE as argument to read options from FILE.\n";
418 }
419 
420 static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
421   // Parse value given with --add-symbol option and create the
422   // new symbol if possible. The value format for --add-symbol is:
423   //
424   // <name>=[<section>:]<value>[,<flags>]
425   //
426   // where:
427   // <name> - symbol name, can be empty string
428   // <section> - optional section name. If not given ABS symbol is created
429   // <value> - symbol value, can be decimal or hexadecimal number prefixed
430   //           with 0x.
431   // <flags> - optional flags affecting symbol type, binding or visibility.
432   NewSymbolInfo SI;
433   StringRef Value;
434   std::tie(SI.SymbolName, Value) = FlagValue.split('=');
435   if (Value.empty())
436     return createStringError(
437         errc::invalid_argument,
438         "bad format for --add-symbol, missing '=' after '%s'",
439         SI.SymbolName.str().c_str());
440 
441   if (Value.contains(':')) {
442     std::tie(SI.SectionName, Value) = Value.split(':');
443     if (SI.SectionName.empty() || Value.empty())
444       return createStringError(
445           errc::invalid_argument,
446           "bad format for --add-symbol, missing section name or symbol value");
447   }
448 
449   SmallVector<StringRef, 6> Flags;
450   Value.split(Flags, ',');
451   if (Flags[0].getAsInteger(0, SI.Value))
452     return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
453                              Flags[0].str().c_str());
454 
455   using Functor = std::function<void()>;
456   SmallVector<StringRef, 6> UnsupportedFlags;
457   for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
458     static_cast<Functor>(
459         StringSwitch<Functor>(Flags[I])
460             .CaseLower("global",
461                        [&] { SI.Flags.push_back(SymbolFlag::Global); })
462             .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); })
463             .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); })
464             .CaseLower("default",
465                        [&] { SI.Flags.push_back(SymbolFlag::Default); })
466             .CaseLower("hidden",
467                        [&] { SI.Flags.push_back(SymbolFlag::Hidden); })
468             .CaseLower("protected",
469                        [&] { SI.Flags.push_back(SymbolFlag::Protected); })
470             .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); })
471             .CaseLower("section",
472                        [&] { SI.Flags.push_back(SymbolFlag::Section); })
473             .CaseLower("object",
474                        [&] { SI.Flags.push_back(SymbolFlag::Object); })
475             .CaseLower("function",
476                        [&] { SI.Flags.push_back(SymbolFlag::Function); })
477             .CaseLower(
478                 "indirect-function",
479                 [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); })
480             .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); })
481             .CaseLower("constructor",
482                        [&] { SI.Flags.push_back(SymbolFlag::Constructor); })
483             .CaseLower("warning",
484                        [&] { SI.Flags.push_back(SymbolFlag::Warning); })
485             .CaseLower("indirect",
486                        [&] { SI.Flags.push_back(SymbolFlag::Indirect); })
487             .CaseLower("synthetic",
488                        [&] { SI.Flags.push_back(SymbolFlag::Synthetic); })
489             .CaseLower("unique-object",
490                        [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); })
491             .StartsWithLower("before=",
492                              [&] {
493                                StringRef SymNamePart =
494                                    Flags[I].split('=').second;
495 
496                                if (!SymNamePart.empty())
497                                  SI.BeforeSyms.push_back(SymNamePart);
498                              })
499             .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
500   if (!UnsupportedFlags.empty())
501     return createStringError(errc::invalid_argument,
502                              "unsupported flag%s for --add-symbol: '%s'",
503                              UnsupportedFlags.size() > 1 ? "s" : "",
504                              join(UnsupportedFlags, "', '").c_str());
505 
506   return SI;
507 }
508 
509 // Parse input option \p ArgValue and load section data. This function
510 // extracts section name and name of the file keeping section data from
511 // ArgValue, loads data from the file, and stores section name and data
512 // into the vector of new sections \p NewSections.
513 static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
514                                 std::vector<NewSectionInfo> &NewSections) {
515   if (!ArgValue.contains('='))
516     return createStringError(errc::invalid_argument,
517                              "bad format for " + OptionName + ": missing '='");
518 
519   std::pair<StringRef, StringRef> SecPair = ArgValue.split("=");
520   if (SecPair.second.empty())
521     return createStringError(errc::invalid_argument, "bad format for " +
522                                                          OptionName +
523                                                          ": missing file name");
524 
525   ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
526       MemoryBuffer::getFile(SecPair.second);
527   if (!BufOrErr)
528     return createFileError(SecPair.second,
529                            errorCodeToError(BufOrErr.getError()));
530 
531   NewSections.push_back({SecPair.first, std::move(*BufOrErr)});
532   return Error::success();
533 }
534 
535 // parseObjcopyOptions returns the config and sets the input arguments. If a
536 // help flag is set then parseObjcopyOptions will print the help messege and
537 // exit.
538 Expected<DriverConfig>
539 objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
540                              function_ref<Error(Error)> ErrorCallback) {
541   DriverConfig DC;
542   ObjcopyOptTable T;
543 
544   const char *const *DashDash =
545       llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
546   ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
547   if (DashDash != RawArgsArr.end())
548     DashDash = std::next(DashDash);
549 
550   unsigned MissingArgumentIndex, MissingArgumentCount;
551   llvm::opt::InputArgList InputArgs =
552       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
553 
554   if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
555     printHelp(T, errs(), ToolType::Objcopy);
556     exit(1);
557   }
558 
559   if (InputArgs.hasArg(OBJCOPY_help)) {
560     printHelp(T, outs(), ToolType::Objcopy);
561     exit(0);
562   }
563 
564   if (InputArgs.hasArg(OBJCOPY_version)) {
565     outs() << "llvm-objcopy, compatible with GNU objcopy\n";
566     cl::PrintVersionMessage();
567     exit(0);
568   }
569 
570   SmallVector<const char *, 2> Positional;
571 
572   for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
573     return createStringError(errc::invalid_argument, "unknown argument '%s'",
574                              Arg->getAsString(InputArgs).c_str());
575 
576   for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
577     Positional.push_back(Arg->getValue());
578   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
579 
580   if (Positional.empty())
581     return createStringError(errc::invalid_argument, "no input file specified");
582 
583   if (Positional.size() > 2)
584     return createStringError(errc::invalid_argument,
585                              "too many positional arguments");
586 
587   ConfigManager ConfigMgr;
588   CommonConfig &Config = ConfigMgr.Common;
589   COFFConfig &COFFConfig = ConfigMgr.COFF;
590   ELFConfig &ELFConfig = ConfigMgr.ELF;
591   MachOConfig &MachOConfig = ConfigMgr.MachO;
592   Config.InputFilename = Positional[0];
593   Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
594   if (InputArgs.hasArg(OBJCOPY_target) &&
595       (InputArgs.hasArg(OBJCOPY_input_target) ||
596        InputArgs.hasArg(OBJCOPY_output_target)))
597     return createStringError(
598         errc::invalid_argument,
599         "--target cannot be used with --input-target or --output-target");
600 
601   if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
602     return createStringError(errc::invalid_argument,
603                              "--regex and --wildcard are incompatible");
604 
605   MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
606                                      ? MatchStyle::Regex
607                                      : MatchStyle::Wildcard;
608   MatchStyle SymbolMatchStyle
609       = InputArgs.hasArg(OBJCOPY_regex)    ? MatchStyle::Regex
610       : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard
611                                            : MatchStyle::Literal;
612   StringRef InputFormat, OutputFormat;
613   if (InputArgs.hasArg(OBJCOPY_target)) {
614     InputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
615     OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
616   } else {
617     InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
618     OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
619   }
620 
621   // FIXME:  Currently, we ignore the target for non-binary/ihex formats
622   // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the
623   // format by llvm::object::createBinary regardless of the option value.
624   Config.InputFormat = StringSwitch<FileFormat>(InputFormat)
625                            .Case("binary", FileFormat::Binary)
626                            .Case("ihex", FileFormat::IHex)
627                            .Default(FileFormat::Unspecified);
628 
629   if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) {
630     const uint8_t Invalid = 0xff;
631     StringRef VisibilityStr =
632         InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
633 
634     ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr)
635                                         .Case("default", ELF::STV_DEFAULT)
636                                         .Case("hidden", ELF::STV_HIDDEN)
637                                         .Case("internal", ELF::STV_INTERNAL)
638                                         .Case("protected", ELF::STV_PROTECTED)
639                                         .Default(Invalid);
640 
641     if (ELFConfig.NewSymbolVisibility == Invalid)
642       return createStringError(errc::invalid_argument,
643                                "'%s' is not a valid symbol visibility",
644                                VisibilityStr.str().c_str());
645   }
646 
647   for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) {
648     StringRef Subsystem, Version;
649     std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':');
650     COFFConfig.Subsystem =
651         StringSwitch<unsigned>(Subsystem.lower())
652             .Case("boot_application",
653                   COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
654             .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
655             .Case("efi_application", COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION)
656             .Case("efi_boot_service_driver",
657                   COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
658             .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM)
659             .Case("efi_runtime_driver",
660                   COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
661             .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE)
662             .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI)
663             .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
664             .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN);
665     if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN)
666       return createStringError(errc::invalid_argument,
667                                "'%s' is not a valid subsystem",
668                                Subsystem.str().c_str());
669     if (!Version.empty()) {
670       StringRef Major, Minor;
671       std::tie(Major, Minor) = Version.split('.');
672       unsigned Number;
673       if (Major.getAsInteger(10, Number))
674         return createStringError(errc::invalid_argument,
675                                  "'%s' is not a valid subsystem major version",
676                                  Major.str().c_str());
677       COFFConfig.MajorSubsystemVersion = Number;
678       Number = 0;
679       if (!Minor.empty() && Minor.getAsInteger(10, Number))
680         return createStringError(errc::invalid_argument,
681                                  "'%s' is not a valid subsystem minor version",
682                                  Minor.str().c_str());
683       COFFConfig.MinorSubsystemVersion = Number;
684     }
685   }
686 
687   Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
688                             .Case("binary", FileFormat::Binary)
689                             .Case("ihex", FileFormat::IHex)
690                             .Default(FileFormat::Unspecified);
691   if (Config.OutputFormat == FileFormat::Unspecified) {
692     if (OutputFormat.empty()) {
693       Config.OutputFormat = Config.InputFormat;
694     } else {
695       Expected<TargetInfo> Target =
696           getOutputTargetInfoByTargetName(OutputFormat);
697       if (!Target)
698         return Target.takeError();
699       Config.OutputFormat = Target->Format;
700       Config.OutputArch = Target->Machine;
701     }
702   }
703 
704   if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) {
705     Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue())
706                                  .Case("zlib", DebugCompressionType::Zlib)
707                                  .Case("zstd", DebugCompressionType::Zstd)
708                                  .Default(DebugCompressionType::None);
709     if (Config.CompressionType == DebugCompressionType::None) {
710       return createStringError(
711           errc::invalid_argument,
712           "invalid or unsupported --compress-debug-sections format: %s",
713           A->getValue());
714     }
715     if (const char *Reason = compression::getReasonIfUnsupported(
716             compression::formatFor(Config.CompressionType)))
717       return createStringError(errc::invalid_argument, Reason);
718   }
719 
720   Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
721   // The gnu_debuglink's target is expected to not change or else its CRC would
722   // become invalidated and get rejected. We can avoid recalculating the
723   // checksum for every target file inside an archive by precomputing the CRC
724   // here. This prevents a significant amount of I/O.
725   if (!Config.AddGnuDebugLink.empty()) {
726     auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink);
727     if (!DebugOrErr)
728       return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());
729     auto Debug = std::move(*DebugOrErr);
730     Config.GnuDebugLinkCRC32 =
731         llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
732   }
733   Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
734   Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
735   Config.AllocSectionsPrefix =
736       InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
737   if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
738     Config.ExtractPartition = Arg->getValue();
739 
740   if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) {
741     if (Config.OutputFormat != FileFormat::Binary)
742       return createStringError(
743           errc::invalid_argument,
744           "'--gap-fill' is only supported for binary output");
745     ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue());
746     if (!Val)
747       return createStringError(Val.getError(), "--gap-fill: bad number: %s",
748                                A->getValue());
749     uint8_t ByteVal = Val.get();
750     if (ByteVal != Val.get())
751       return createStringError(std::errc::value_too_large,
752                                "gap-fill value %s is out of range (0 to 0xff)",
753                                A->getValue());
754     Config.GapFill = ByteVal;
755   }
756 
757   if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) {
758     if (Config.OutputFormat != FileFormat::Binary)
759       return createStringError(
760           errc::invalid_argument,
761           "'--pad-to' is only supported for binary output");
762     ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue());
763     if (!Addr)
764       return createStringError(Addr.getError(), "--pad-to: bad number: %s",
765                                A->getValue());
766     Config.PadTo = *Addr;
767   }
768 
769   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
770     if (!StringRef(Arg->getValue()).contains('='))
771       return createStringError(errc::invalid_argument,
772                                "bad format for --redefine-sym");
773     auto Old2New = StringRef(Arg->getValue()).split('=');
774     if (!Config.SymbolsToRename.insert(Old2New).second)
775       return createStringError(errc::invalid_argument,
776                                "multiple redefinition of symbol '%s'",
777                                Old2New.first.str().c_str());
778   }
779 
780   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
781     if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
782                                              Arg->getValue()))
783       return std::move(E);
784 
785   for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
786     Expected<SectionRename> SR =
787         parseRenameSectionValue(StringRef(Arg->getValue()));
788     if (!SR)
789       return SR.takeError();
790     if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
791       return createStringError(errc::invalid_argument,
792                                "multiple renames of section '%s'",
793                                SR->OriginalName.str().c_str());
794   }
795   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
796     Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
797         parseSetSectionAttribute("--set-section-alignment", Arg->getValue());
798     if (!NameAndAlign)
799       return NameAndAlign.takeError();
800     Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
801   }
802   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
803     Expected<SectionFlagsUpdate> SFU =
804         parseSetSectionFlagValue(Arg->getValue());
805     if (!SFU)
806       return SFU.takeError();
807     if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
808       return createStringError(
809           errc::invalid_argument,
810           "--set-section-flags set multiple times for section '%s'",
811           SFU->Name.str().c_str());
812   }
813   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) {
814     Expected<std::pair<StringRef, uint64_t>> NameAndType =
815         parseSetSectionAttribute("--set-section-type", Arg->getValue());
816     if (!NameAndType)
817       return NameAndType.takeError();
818     Config.SetSectionType[NameAndType->first] = NameAndType->second;
819   }
820   // Prohibit combinations of --set-section-{flags,type} when the section name
821   // is used as the destination of a --rename-section.
822   for (const auto &E : Config.SectionsToRename) {
823     const SectionRename &SR = E.second;
824     auto Err = [&](const char *Option) {
825       return createStringError(
826           errc::invalid_argument,
827           "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option,
828           SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
829           SR.NewName.str().c_str());
830     };
831     if (Config.SetSectionFlags.count(SR.NewName))
832       return Err("flags");
833     if (Config.SetSectionType.count(SR.NewName))
834       return Err("type");
835   }
836 
837   for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section))
838     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
839             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
840       return std::move(E);
841   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section))
842     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
843             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
844       return std::move(E);
845   for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section))
846     if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
847             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
848       return std::move(E);
849   for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) {
850     if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section",
851                                        Config.AddSection))
852       return std::move(Err);
853   }
854   for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) {
855     if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section",
856                                        Config.UpdateSection))
857       return std::move(Err);
858   }
859   for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
860     StringRef Value(Arg->getValue());
861     if (Value.split('=').second.empty())
862       return createStringError(
863           errc::invalid_argument,
864           "bad format for --dump-section, expected section=file");
865     Config.DumpSection.push_back(Value);
866   }
867   Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
868   Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
869   Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
870   Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
871   Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
872   Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
873   Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
874   Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
875   Config.ExtractMainPartition =
876       InputArgs.hasArg(OBJCOPY_extract_main_partition);
877   ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
878   Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
879   if (auto *Arg =
880           InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
881     Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all)
882                              ? DiscardType::All
883                              : DiscardType::Locals;
884   }
885   Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
886   ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
887   MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
888   Config.DecompressDebugSections =
889       InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
890   if (Config.DiscardMode == DiscardType::All) {
891     Config.StripDebug = true;
892     ELFConfig.KeepFileSymbols = true;
893   }
894   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
895     if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
896             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
897       return std::move(E);
898   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
899     if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
900                                      Arg->getValue(), SymbolMatchStyle,
901                                      ErrorCallback))
902       return std::move(E);
903   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
904     if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
905             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
906       return std::move(E);
907   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
908     if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
909                                      Arg->getValue(), SymbolMatchStyle,
910                                      ErrorCallback))
911       return std::move(E);
912   for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
913     if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
914             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
915       return std::move(E);
916   for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
917     if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
918                                      Arg->getValue(), SymbolMatchStyle,
919                                      ErrorCallback))
920       return std::move(E);
921   for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
922     if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
923             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
924       return std::move(E);
925   for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
926     if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
927                                      Arg->getValue(), SymbolMatchStyle,
928                                      ErrorCallback))
929       return std::move(E);
930   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
931     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
932             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
933       return std::move(E);
934   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
935     if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
936                                      Arg->getValue(), SymbolMatchStyle,
937                                      ErrorCallback))
938       return std::move(E);
939   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
940     if (Error E =
941             Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
942                 Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
943       return std::move(E);
944   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
945     if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
946                                      Arg->getValue(), SymbolMatchStyle,
947                                      ErrorCallback))
948       return std::move(E);
949   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
950     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
951             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
952       return std::move(E);
953   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
954     if (Error E =
955             addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
956                                SymbolMatchStyle, ErrorCallback))
957       return std::move(E);
958   for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
959     Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
960     if (!SymInfo)
961       return SymInfo.takeError();
962 
963     Config.SymbolsToAdd.push_back(*SymInfo);
964   }
965 
966   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
967 
968   Config.DeterministicArchives = InputArgs.hasFlag(
969       OBJCOPY_enable_deterministic_archives,
970       OBJCOPY_disable_deterministic_archives, /*default=*/true);
971 
972   Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
973 
974   if (Config.PreserveDates &&
975       (Config.OutputFilename == "-" || Config.InputFilename == "-"))
976     return createStringError(errc::invalid_argument,
977                              "--preserve-dates requires a file");
978 
979   for (auto *Arg : InputArgs)
980     if (Arg->getOption().matches(OBJCOPY_set_start)) {
981       auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
982       if (!EAddr)
983         return createStringError(
984             EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
985 
986       ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
987     } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
988       auto EIncr = getAsInteger<int64_t>(Arg->getValue());
989       if (!EIncr)
990         return createStringError(EIncr.getError(),
991                                  "bad entry point increment: '%s'",
992                                  Arg->getValue());
993       auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr)
994                                       : [](uint64_t A) { return A; };
995       ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
996         return Expr(EAddr) + *EIncr;
997       };
998     }
999 
1000   if (Config.DecompressDebugSections &&
1001       Config.CompressionType != DebugCompressionType::None) {
1002     return createStringError(
1003         errc::invalid_argument,
1004         "cannot specify both --compress-debug-sections and "
1005         "--decompress-debug-sections");
1006   }
1007 
1008   if (Config.ExtractPartition && Config.ExtractMainPartition)
1009     return createStringError(errc::invalid_argument,
1010                              "cannot specify --extract-partition together with "
1011                              "--extract-main-partition");
1012 
1013   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1014   return std::move(DC);
1015 }
1016 
1017 // parseInstallNameToolOptions returns the config and sets the input arguments.
1018 // If a help flag is set then parseInstallNameToolOptions will print the help
1019 // messege and exit.
1020 Expected<DriverConfig>
1021 objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
1022   DriverConfig DC;
1023   ConfigManager ConfigMgr;
1024   CommonConfig &Config = ConfigMgr.Common;
1025   MachOConfig &MachOConfig = ConfigMgr.MachO;
1026   InstallNameToolOptTable T;
1027   unsigned MissingArgumentIndex, MissingArgumentCount;
1028   llvm::opt::InputArgList InputArgs =
1029       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1030 
1031   if (MissingArgumentCount)
1032     return createStringError(
1033         errc::invalid_argument,
1034         "missing argument to " +
1035             StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
1036             " option");
1037 
1038   if (InputArgs.size() == 0) {
1039     printHelp(T, errs(), ToolType::InstallNameTool);
1040     exit(1);
1041   }
1042 
1043   if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
1044     printHelp(T, outs(), ToolType::InstallNameTool);
1045     exit(0);
1046   }
1047 
1048   if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
1049     outs() << "llvm-install-name-tool, compatible with cctools "
1050               "install_name_tool\n";
1051     cl::PrintVersionMessage();
1052     exit(0);
1053   }
1054 
1055   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
1056     MachOConfig.RPathToAdd.push_back(Arg->getValue());
1057 
1058   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
1059     MachOConfig.RPathToPrepend.push_back(Arg->getValue());
1060 
1061   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
1062     StringRef RPath = Arg->getValue();
1063 
1064     // Cannot add and delete the same rpath at the same time.
1065     if (is_contained(MachOConfig.RPathToAdd, RPath))
1066       return createStringError(
1067           errc::invalid_argument,
1068           "cannot specify both -add_rpath '%s' and -delete_rpath '%s'",
1069           RPath.str().c_str(), RPath.str().c_str());
1070     if (is_contained(MachOConfig.RPathToPrepend, RPath))
1071       return createStringError(
1072           errc::invalid_argument,
1073           "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'",
1074           RPath.str().c_str(), RPath.str().c_str());
1075 
1076     MachOConfig.RPathsToRemove.insert(RPath);
1077   }
1078 
1079   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) {
1080     StringRef Old = Arg->getValue(0);
1081     StringRef New = Arg->getValue(1);
1082 
1083     auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; };
1084 
1085     // Cannot specify duplicate -rpath entries
1086     auto It1 = find_if(
1087         MachOConfig.RPathsToUpdate,
1088         [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) {
1089           return Match(OldNew.getFirst()) || Match(OldNew.getSecond());
1090         });
1091     if (It1 != MachOConfig.RPathsToUpdate.end())
1092       return createStringError(errc::invalid_argument,
1093                                "cannot specify both -rpath '" +
1094                                    It1->getFirst() + "' '" + It1->getSecond() +
1095                                    "' and -rpath '" + Old + "' '" + New + "'");
1096 
1097     // Cannot specify the same rpath under both -delete_rpath and -rpath
1098     auto It2 = find_if(MachOConfig.RPathsToRemove, Match);
1099     if (It2 != MachOConfig.RPathsToRemove.end())
1100       return createStringError(errc::invalid_argument,
1101                                "cannot specify both -delete_rpath '" + *It2 +
1102                                    "' and -rpath '" + Old + "' '" + New + "'");
1103 
1104     // Cannot specify the same rpath under both -add_rpath and -rpath
1105     auto It3 = find_if(MachOConfig.RPathToAdd, Match);
1106     if (It3 != MachOConfig.RPathToAdd.end())
1107       return createStringError(errc::invalid_argument,
1108                                "cannot specify both -add_rpath '" + *It3 +
1109                                    "' and -rpath '" + Old + "' '" + New + "'");
1110 
1111     // Cannot specify the same rpath under both -prepend_rpath and -rpath.
1112     auto It4 = find_if(MachOConfig.RPathToPrepend, Match);
1113     if (It4 != MachOConfig.RPathToPrepend.end())
1114       return createStringError(errc::invalid_argument,
1115                                "cannot specify both -prepend_rpath '" + *It4 +
1116                                    "' and -rpath '" + Old + "' '" + New + "'");
1117 
1118     MachOConfig.RPathsToUpdate.insert({Old, New});
1119   }
1120 
1121   if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) {
1122     MachOConfig.SharedLibId = Arg->getValue();
1123     if (MachOConfig.SharedLibId->empty())
1124       return createStringError(errc::invalid_argument,
1125                                "cannot specify an empty id");
1126   }
1127 
1128   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change))
1129     MachOConfig.InstallNamesToUpdate.insert(
1130         {Arg->getValue(0), Arg->getValue(1)});
1131 
1132   MachOConfig.RemoveAllRpaths =
1133       InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);
1134 
1135   SmallVector<StringRef, 2> Positional;
1136   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
1137     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1138                              Arg->getAsString(InputArgs).c_str());
1139   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
1140     Positional.push_back(Arg->getValue());
1141   if (Positional.empty())
1142     return createStringError(errc::invalid_argument, "no input file specified");
1143   if (Positional.size() > 1)
1144     return createStringError(
1145         errc::invalid_argument,
1146         "llvm-install-name-tool expects a single input file");
1147   Config.InputFilename = Positional[0];
1148   Config.OutputFilename = Positional[0];
1149 
1150   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1151   return std::move(DC);
1152 }
1153 
1154 Expected<DriverConfig>
1155 objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
1156                                   function_ref<Error(Error)> ErrorCallback) {
1157   DriverConfig DC;
1158   ConfigManager ConfigMgr;
1159   CommonConfig &Config = ConfigMgr.Common;
1160   MachOConfig &MachOConfig = ConfigMgr.MachO;
1161   BitcodeStripOptTable T;
1162   unsigned MissingArgumentIndex, MissingArgumentCount;
1163   opt::InputArgList InputArgs =
1164       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1165 
1166   if (InputArgs.size() == 0) {
1167     printHelp(T, errs(), ToolType::BitcodeStrip);
1168     exit(1);
1169   }
1170 
1171   if (InputArgs.hasArg(BITCODE_STRIP_help)) {
1172     printHelp(T, outs(), ToolType::BitcodeStrip);
1173     exit(0);
1174   }
1175 
1176   if (InputArgs.hasArg(BITCODE_STRIP_version)) {
1177     outs() << "llvm-bitcode-strip, compatible with cctools "
1178               "bitcode_strip\n";
1179     cl::PrintVersionMessage();
1180     exit(0);
1181   }
1182 
1183   for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN))
1184     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1185                              Arg->getAsString(InputArgs).c_str());
1186 
1187   SmallVector<StringRef, 2> Positional;
1188   for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
1189     Positional.push_back(Arg->getValue());
1190   if (Positional.size() > 1)
1191     return createStringError(errc::invalid_argument,
1192                              "llvm-bitcode-strip expects a single input file");
1193   assert(!Positional.empty());
1194   Config.InputFilename = Positional[0];
1195 
1196   if (!InputArgs.hasArg(BITCODE_STRIP_output)) {
1197     return createStringError(errc::invalid_argument,
1198                              "-o is a required argument");
1199   }
1200   Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output);
1201 
1202   if (!InputArgs.hasArg(BITCODE_STRIP_remove))
1203     return createStringError(errc::invalid_argument, "no action specified");
1204 
1205   // We only support -r for now, which removes all bitcode sections and
1206   // the __LLVM segment if it's now empty.
1207   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1208       "__LLVM,__asm", MatchStyle::Literal, ErrorCallback)));
1209   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1210       "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback)));
1211   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1212       "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback)));
1213   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1214       "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback)));
1215   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1216       "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback)));
1217   MachOConfig.EmptySegmentsToRemove.insert("__LLVM");
1218 
1219   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1220   return std::move(DC);
1221 }
1222 
1223 // parseStripOptions returns the config and sets the input arguments. If a
1224 // help flag is set then parseStripOptions will print the help messege and
1225 // exit.
1226 Expected<DriverConfig>
1227 objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
1228                            function_ref<Error(Error)> ErrorCallback) {
1229   const char *const *DashDash =
1230       llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
1231   ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
1232   if (DashDash != RawArgsArr.end())
1233     DashDash = std::next(DashDash);
1234 
1235   StripOptTable T;
1236   unsigned MissingArgumentIndex, MissingArgumentCount;
1237   llvm::opt::InputArgList InputArgs =
1238       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1239 
1240   if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
1241     printHelp(T, errs(), ToolType::Strip);
1242     exit(1);
1243   }
1244 
1245   if (InputArgs.hasArg(STRIP_help)) {
1246     printHelp(T, outs(), ToolType::Strip);
1247     exit(0);
1248   }
1249 
1250   if (InputArgs.hasArg(STRIP_version)) {
1251     outs() << "llvm-strip, compatible with GNU strip\n";
1252     cl::PrintVersionMessage();
1253     exit(0);
1254   }
1255 
1256   SmallVector<StringRef, 2> Positional;
1257   for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
1258     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1259                              Arg->getAsString(InputArgs).c_str());
1260   for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
1261     Positional.push_back(Arg->getValue());
1262   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
1263 
1264   if (Positional.empty())
1265     return createStringError(errc::invalid_argument, "no input file specified");
1266 
1267   if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
1268     return createStringError(
1269         errc::invalid_argument,
1270         "multiple input files cannot be used in combination with -o");
1271 
1272   ConfigManager ConfigMgr;
1273   CommonConfig &Config = ConfigMgr.Common;
1274   ELFConfig &ELFConfig = ConfigMgr.ELF;
1275   MachOConfig &MachOConfig = ConfigMgr.MachO;
1276 
1277   if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
1278     return createStringError(errc::invalid_argument,
1279                              "--regex and --wildcard are incompatible");
1280   MatchStyle SectionMatchStyle =
1281       InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
1282   MatchStyle SymbolMatchStyle
1283       = InputArgs.hasArg(STRIP_regex)    ? MatchStyle::Regex
1284       : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard
1285                                          : MatchStyle::Literal;
1286   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
1287   Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
1288 
1289   if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals))
1290     Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all)
1291                              ? DiscardType::All
1292                              : DiscardType::Locals;
1293   Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
1294   Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
1295   if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
1296     Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
1297   Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
1298   MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
1299   Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
1300   ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
1301   MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
1302 
1303   for (auto *Arg : InputArgs.filtered(STRIP_keep_section))
1304     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
1305             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1306       return std::move(E);
1307 
1308   for (auto *Arg : InputArgs.filtered(STRIP_remove_section))
1309     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
1310             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1311       return std::move(E);
1312 
1313   for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol))
1314     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
1315             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1316       return std::move(E);
1317 
1318   for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol))
1319     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
1320             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1321       return std::move(E);
1322 
1323   if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
1324       !Config.OnlyKeepDebug && !Config.StripUnneeded &&
1325       Config.DiscardMode == DiscardType::None && !Config.StripAllGNU &&
1326       Config.SymbolsToRemove.empty())
1327     Config.StripAll = true;
1328 
1329   if (Config.DiscardMode == DiscardType::All) {
1330     Config.StripDebug = true;
1331     ELFConfig.KeepFileSymbols = true;
1332   }
1333 
1334   Config.DeterministicArchives =
1335       InputArgs.hasFlag(STRIP_enable_deterministic_archives,
1336                         STRIP_disable_deterministic_archives, /*default=*/true);
1337 
1338   Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
1339   Config.InputFormat = FileFormat::Unspecified;
1340   Config.OutputFormat = FileFormat::Unspecified;
1341 
1342   DriverConfig DC;
1343   if (Positional.size() == 1) {
1344     Config.InputFilename = Positional[0];
1345     Config.OutputFilename =
1346         InputArgs.getLastArgValue(STRIP_output, Positional[0]);
1347     DC.CopyConfigs.push_back(std::move(ConfigMgr));
1348   } else {
1349     StringMap<unsigned> InputFiles;
1350     for (StringRef Filename : Positional) {
1351       if (InputFiles[Filename]++ == 1) {
1352         if (Filename == "-")
1353           return createStringError(
1354               errc::invalid_argument,
1355               "cannot specify '-' as an input file more than once");
1356         if (Error E = ErrorCallback(createStringError(
1357                 errc::invalid_argument, "'%s' was already specified",
1358                 Filename.str().c_str())))
1359           return std::move(E);
1360       }
1361       Config.InputFilename = Filename;
1362       Config.OutputFilename = Filename;
1363       DC.CopyConfigs.push_back(ConfigMgr);
1364     }
1365   }
1366 
1367   if (Config.PreserveDates && (is_contained(Positional, "-") ||
1368                                InputArgs.getLastArgValue(STRIP_output) == "-"))
1369     return createStringError(errc::invalid_argument,
1370                              "--preserve-dates requires a file");
1371 
1372   return std::move(DC);
1373 }
1374