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