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