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