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