159191Skris//===- ObjcopyOptions.cpp -------------------------------------------------===//
259191Skris//
359191Skris// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
459191Skris// See https://llvm.org/LICENSE.txt for license information.
559191Skris// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659191Skris//
759191Skris//===----------------------------------------------------------------------===//
859191Skris
959191Skris#include "ObjcopyOptions.h"
1059191Skris#include "llvm/ADT/SmallVector.h"
11238405Sjkim#include "llvm/ADT/StringExtras.h"
1259191Skris#include "llvm/ADT/StringRef.h"
1359191Skris#include "llvm/BinaryFormat/COFF.h"
1459191Skris#include "llvm/ObjCopy/CommonConfig.h"
1559191Skris#include "llvm/ObjCopy/ConfigManager.h"
1659191Skris#include "llvm/ObjCopy/MachO/MachOConfig.h"
1759191Skris#include "llvm/Option/Arg.h"
1859191Skris#include "llvm/Option/ArgList.h"
19238405Sjkim#include "llvm/Support/CRC.h"
2059191Skris#include "llvm/Support/CommandLine.h"
2159191Skris#include "llvm/Support/Compression.h"
2259191Skris#include "llvm/Support/Errc.h"
2359191Skris#include "llvm/Support/Error.h"
2459191Skris#include "llvm/Support/MemoryBuffer.h"
2559191Skris
2659191Skrisusing namespace llvm;
2759191Skrisusing namespace llvm::objcopy;
2859191Skrisusing namespace llvm::opt;
29238405Sjkim
3068651Skrisnamespace {
3168651Skrisenum ObjcopyID {
3259191Skris  OBJCOPY_INVALID = 0, // This is not an option ID.
3368651Skris#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
3468651Skris#include "ObjcopyOpts.inc"
3568651Skris#undef OPTION
3659191Skris};
37238405Sjkim
38238405Sjkimnamespace objcopy_opt {
39269686Sjkim#define PREFIX(NAME, VALUE)                                                    \
40238405Sjkim  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
41296317Sdelphij  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
4259191Skris                                                std::size(NAME##_init) - 1);
43296317Sdelphij#include "ObjcopyOpts.inc"
4459191Skris#undef PREFIX
4559191Skris
4659191Skrisstatic constexpr opt::OptTable::Info ObjcopyInfoTable[] = {
47296317Sdelphij#define OPTION(...)                                                            \
4859191Skris  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
4959191Skris#include "ObjcopyOpts.inc"
5059191Skris#undef OPTION
51296317Sdelphij};
5259191Skris} // namespace objcopy_opt
5359191Skris
5459191Skrisclass ObjcopyOptTable : public opt::GenericOptTable {
55296317Sdelphijpublic:
5659191Skris  ObjcopyOptTable() : opt::GenericOptTable(objcopy_opt::ObjcopyInfoTable) {
5759191Skris    setGroupedShortOptions(true);
5859191Skris  }
5959191Skris};
6059191Skris
6159191Skrisenum InstallNameToolID {
6259191Skris  INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
6359191Skris#define OPTION(...)                                                            \
6459191Skris  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
6559191Skris#include "InstallNameToolOpts.inc"
6659191Skris#undef OPTION
6759191Skris};
6859191Skris
6959191Skrisnamespace install_name_tool {
7059191Skris
7159191Skris#define PREFIX(NAME, VALUE)                                                    \
7259191Skris  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
7359191Skris  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
7459191Skris                                                std::size(NAME##_init) - 1);
7559191Skris#include "InstallNameToolOpts.inc"
7659191Skris#undef PREFIX
7759191Skris
7859191Skrisstatic constexpr opt::OptTable::Info InstallNameToolInfoTable[] = {
7959191Skris#define OPTION(...)                                                            \
8059191Skris  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
8159191Skris#include "InstallNameToolOpts.inc"
8259191Skris#undef OPTION
8359191Skris};
8459191Skris} // namespace install_name_tool
8559191Skris
8659191Skrisclass InstallNameToolOptTable : public opt::GenericOptTable {
8759191Skrispublic:
8859191Skris  InstallNameToolOptTable()
8959191Skris      : GenericOptTable(install_name_tool::InstallNameToolInfoTable) {}
9059191Skris};
9159191Skris
9259191Skrisenum BitcodeStripID {
9359191Skris  BITCODE_STRIP_INVALID = 0, // This is not an option ID.
9459191Skris#define OPTION(...)                                                            \
9559191Skris  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
9659191Skris#include "BitcodeStripOpts.inc"
9759191Skris#undef OPTION
9859191Skris};
9959191Skris
10059191Skrisnamespace bitcode_strip {
10159191Skris
10259191Skris#define PREFIX(NAME, VALUE)                                                    \
10359191Skris  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
10459191Skris  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
10559191Skris                                                std::size(NAME##_init) - 1);
10659191Skris#include "BitcodeStripOpts.inc"
10759191Skris#undef PREFIX
108296317Sdelphij
109296317Sdelphijstatic constexpr opt::OptTable::Info BitcodeStripInfoTable[] = {
110298999Sjkim#define OPTION(...)                                                            \
111296317Sdelphij  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
11259191Skris#include "BitcodeStripOpts.inc"
113109998Smarkm#undef OPTION
114109998Smarkm};
115109998Smarkm} // namespace bitcode_strip
116269686Sjkim
117269686Sjkimclass BitcodeStripOptTable : public opt::GenericOptTable {
118109998Smarkmpublic:
11959191Skris  BitcodeStripOptTable()
12059191Skris      : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable) {}
121238405Sjkim};
122238405Sjkim
12359191Skrisenum StripID {
124109998Smarkm  STRIP_INVALID = 0, // This is not an option ID.
125109998Smarkm#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
126109998Smarkm#include "StripOpts.inc"
127109998Smarkm#undef OPTION
12859191Skris};
12959191Skris
13059191Skrisnamespace strip {
131162911Ssimon#define PREFIX(NAME, VALUE)                                                    \
13259191Skris  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
13359191Skris  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
13459191Skris                                                std::size(NAME##_init) - 1);
135162911Ssimon#include "StripOpts.inc"
13659191Skris#undef PREFIX
13759191Skris
13859191Skrisstatic constexpr opt::OptTable::Info StripInfoTable[] = {
139296317Sdelphij#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
140296317Sdelphij#include "StripOpts.inc"
141296317Sdelphij#undef OPTION
14259191Skris};
14359191Skris} // namespace strip
14459191Skris
145296317Sdelphijclass StripOptTable : public opt::GenericOptTable {
146296317Sdelphijpublic:
14759191Skris  StripOptTable() : GenericOptTable(strip::StripInfoTable) {
14859191Skris    setGroupedShortOptions(true);
14959191Skris  }
150296317Sdelphij};
151296317Sdelphij
15259191Skris} // namespace
15359191Skris
15459191Skrisstatic SectionFlag parseSectionRenameFlag(StringRef SectionName) {
155296317Sdelphij  return llvm::StringSwitch<SectionFlag>(SectionName)
156167612Ssimon      .CaseLower("alloc", SectionFlag::SecAlloc)
157167612Ssimon      .CaseLower("load", SectionFlag::SecLoad)
158296317Sdelphij      .CaseLower("noload", SectionFlag::SecNoload)
15959191Skris      .CaseLower("readonly", SectionFlag::SecReadonly)
16059191Skris      .CaseLower("debug", SectionFlag::SecDebug)
16159191Skris      .CaseLower("code", SectionFlag::SecCode)
162296317Sdelphij      .CaseLower("data", SectionFlag::SecData)
163296317Sdelphij      .CaseLower("rom", SectionFlag::SecRom)
164296317Sdelphij      .CaseLower("merge", SectionFlag::SecMerge)
165296317Sdelphij      .CaseLower("strings", SectionFlag::SecStrings)
166296317Sdelphij      .CaseLower("contents", SectionFlag::SecContents)
167296317Sdelphij      .CaseLower("share", SectionFlag::SecShare)
16859191Skris      .CaseLower("exclude", SectionFlag::SecExclude)
16959191Skris      .CaseLower("large", SectionFlag::SecLarge)
17059191Skris      .Default(SectionFlag::SecNone);
171296317Sdelphij}
172269686Sjkim
173269686Sjkimstatic Expected<SectionFlag>
174296317SdelphijparseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
175296317Sdelphij  SectionFlag ParsedFlags = SectionFlag::SecNone;
176296317Sdelphij  for (StringRef Flag : SectionFlags) {
177296317Sdelphij    SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
178296317Sdelphij    if (ParsedFlag == SectionFlag::SecNone)
17959191Skris      return createStringError(
18059191Skris          errc::invalid_argument,
18159191Skris          "unrecognized section flag '%s'. Flags supported for GNU "
18259191Skris          "compatibility: alloc, load, noload, readonly, exclude, debug, "
18359191Skris          "code, data, rom, share, contents, merge, strings, large",
184269686Sjkim          Flag.str().c_str());
185269686Sjkim    ParsedFlags |= ParsedFlag;
186269686Sjkim  }
187269686Sjkim
188269686Sjkim  return ParsedFlags;
18959191Skris}
19059191Skris
191269686Sjkimstatic Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {
192269686Sjkim  if (!FlagValue.contains('='))
19359191Skris    return createStringError(errc::invalid_argument,
194269686Sjkim                             "bad format for --rename-section: missing '='");
19559191Skris
196269686Sjkim  // Initial split: ".foo" = ".bar,f1,f2,..."
19759191Skris  auto Old2New = FlagValue.split('=');
198269686Sjkim  SectionRename SR;
199269686Sjkim  SR.OriginalName = Old2New.first;
200269686Sjkim
201269686Sjkim  // Flags split: ".bar" "f1" "f2" ...
202269686Sjkim  SmallVector<StringRef, 6> NameAndFlags;
203269686Sjkim  Old2New.second.split(NameAndFlags, ',');
204269686Sjkim  SR.NewName = NameAndFlags[0];
205269686Sjkim
206269686Sjkim  if (NameAndFlags.size() > 1) {
207269686Sjkim    Expected<SectionFlag> ParsedFlagSet =
208269686Sjkim        parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front());
209269686Sjkim    if (!ParsedFlagSet)
210269686Sjkim      return ParsedFlagSet.takeError();
211269686Sjkim    SR.NewFlags = *ParsedFlagSet;
212269686Sjkim  }
213269686Sjkim
214269686Sjkim  return SR;
215269686Sjkim}
216269686Sjkim
217291721Sjkimstatic Expected<std::pair<StringRef, uint64_t>>
218269686SjkimparseSetSectionAttribute(StringRef Option, StringRef FlagValue) {
219269686Sjkim  if (!FlagValue.contains('='))
220269686Sjkim    return make_error<StringError>("bad format for " + Option + ": missing '='",
221269686Sjkim                                   errc::invalid_argument);
222269686Sjkim  auto Split = StringRef(FlagValue).split('=');
223269686Sjkim  if (Split.first.empty())
224269686Sjkim    return make_error<StringError>("bad format for " + Option +
225269686Sjkim                                       ": missing section name",
226269686Sjkim                                   errc::invalid_argument);
227269686Sjkim  uint64_t Value;
228269686Sjkim  if (Split.second.getAsInteger(0, Value))
229269686Sjkim    return make_error<StringError>("invalid value for " + Option + ": '" +
23059191Skris                                       Split.second + "'",
23159191Skris                                   errc::invalid_argument);
23259191Skris  return std::make_pair(Split.first, Value);
23359191Skris}
23459191Skris
23559191Skrisstatic Expected<SectionFlagsUpdate>
23659191SkrisparseSetSectionFlagValue(StringRef FlagValue) {
23759191Skris  if (!StringRef(FlagValue).contains('='))
23859191Skris    return createStringError(errc::invalid_argument,
23959191Skris                             "bad format for --set-section-flags: missing '='");
24059191Skris
24159191Skris  // Initial split: ".foo" = "f1,f2,..."
24259191Skris  auto Section2Flags = StringRef(FlagValue).split('=');
243269686Sjkim  SectionFlagsUpdate SFU;
244269686Sjkim  SFU.Name = Section2Flags.first;
245269686Sjkim
246269686Sjkim  // Flags split: "f1" "f2" ...
247269686Sjkim  SmallVector<StringRef, 6> SectionFlags;
248269686Sjkim  Section2Flags.second.split(SectionFlags, ',');
249269686Sjkim  Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags);
250269686Sjkim  if (!ParsedFlagSet)
251269686Sjkim    return ParsedFlagSet.takeError();
252269686Sjkim  SFU.NewFlags = *ParsedFlagSet;
25359191Skris
25459191Skris  return SFU;
25559191Skris}
25659191Skris
25759191Skrisnamespace {
258269686Sjkimstruct TargetInfo {
25959191Skris  FileFormat Format;
260269686Sjkim  MachineInfo Machine;
261269686Sjkim};
26259191Skris} // namespace
263269686Sjkim
26459191Skris// FIXME: consolidate with the bfd parsing used by lld.
265269686Sjkimstatic const StringMap<MachineInfo> TargetMap{
26659191Skris    // Name, {EMachine, 64bit, LittleEndian}
267269686Sjkim    // x86
26859191Skris    {"elf32-i386", {ELF::EM_386, false, true}},
269269686Sjkim    {"elf32-x86-64", {ELF::EM_X86_64, false, true}},
270269686Sjkim    {"elf64-x86-64", {ELF::EM_X86_64, true, true}},
27159191Skris    // Intel MCU
272269686Sjkim    {"elf32-iamcu", {ELF::EM_IAMCU, false, true}},
273109998Smarkm    // ARM
274269686Sjkim    {"elf32-littlearm", {ELF::EM_ARM, false, true}},
275269686Sjkim    // ARM AArch64
276109998Smarkm    {"elf64-aarch64", {ELF::EM_AARCH64, true, true}},
27759191Skris    {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}},
27859191Skris    // RISC-V
27959191Skris    {"elf32-littleriscv", {ELF::EM_RISCV, false, true}},
28059191Skris    {"elf64-littleriscv", {ELF::EM_RISCV, true, true}},
28159191Skris    // PowerPC
28259191Skris    {"elf32-powerpc", {ELF::EM_PPC, false, false}},
28359191Skris    {"elf32-powerpcle", {ELF::EM_PPC, false, true}},
28459191Skris    {"elf64-powerpc", {ELF::EM_PPC64, true, false}},
28559191Skris    {"elf64-powerpcle", {ELF::EM_PPC64, true, true}},
28659191Skris    // MIPS
28759191Skris    {"elf32-bigmips", {ELF::EM_MIPS, false, false}},
28859191Skris    {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}},
28959191Skris    {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}},
29059191Skris    {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}},
29159191Skris    {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}},
29259191Skris    {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}},
29359191Skris    {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}},
29459191Skris    // SPARC
29559191Skris    {"elf32-sparc", {ELF::EM_SPARC, false, false}},
29659191Skris    {"elf32-sparcel", {ELF::EM_SPARC, false, true}},
297194206Ssimon    // Hexagon
298194206Ssimon    {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}},
299194206Ssimon    // LoongArch
300194206Ssimon    {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}},
30159191Skris    {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}},
30259191Skris    // SystemZ
30359191Skris    {"elf64-s390", {ELF::EM_S390, true, false}},
30459191Skris};
30559191Skris
30659191Skrisstatic Expected<TargetInfo>
30759191SkrisgetOutputTargetInfoByTargetName(StringRef TargetName) {
30859191Skris  StringRef OriginalTargetName = TargetName;
309269686Sjkim  bool IsFreeBSD = TargetName.consume_back("-freebsd");
310269686Sjkim  auto Iter = TargetMap.find(TargetName);
311269686Sjkim  if (Iter == std::end(TargetMap))
312269686Sjkim    return createStringError(errc::invalid_argument,
313238405Sjkim                             "invalid output format: '%s'",
314238405Sjkim                             OriginalTargetName.str().c_str());
315238405Sjkim  MachineInfo MI = Iter->getValue();
316238405Sjkim  if (IsFreeBSD)
317238405Sjkim    MI.OSABI = ELF::ELFOSABI_FREEBSD;
318238405Sjkim
319238405Sjkim  FileFormat Format;
320238405Sjkim  if (TargetName.starts_with("elf"))
321238405Sjkim    Format = FileFormat::ELF;
322238405Sjkim  else
323238405Sjkim    // This should never happen because `TargetName` is valid (it certainly
324238405Sjkim    // exists in the TargetMap).
325238405Sjkim    llvm_unreachable("unknown target prefix");
326238405Sjkim
327238405Sjkim  return {TargetInfo{Format, MI}};
328238405Sjkim}
329238405Sjkim
330238405Sjkimstatic Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
331238405Sjkim                                StringRef Filename, MatchStyle MS,
332238405Sjkim                                function_ref<Error(Error)> ErrorCallback) {
333238405Sjkim  StringSaver Saver(Alloc);
334238405Sjkim  SmallVector<StringRef, 16> Lines;
335238405Sjkim  auto BufOrErr = MemoryBuffer::getFile(Filename);
336238405Sjkim  if (!BufOrErr)
337238405Sjkim    return createFileError(Filename, BufOrErr.getError());
338238405Sjkim
339269686Sjkim  BufOrErr.get()->getBuffer().split(Lines, '\n');
340238405Sjkim  for (StringRef Line : Lines) {
341269686Sjkim    // Ignore everything after '#', trim whitespace, and only add the symbol if
342269686Sjkim    // it's not empty.
34359191Skris    auto TrimmedLine = Line.split('#').first.trim();
34459191Skris    if (!TrimmedLine.empty())
34559191Skris      if (Error E = Symbols.addMatcher(NameOrPattern::create(
34659191Skris              Saver.save(TrimmedLine), MS, ErrorCallback)))
34759191Skris        return E;
348109998Smarkm  }
349109998Smarkm
350109998Smarkm  return Error::success();
35159191Skris}
35259191Skris
35359191Skrisstatic Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
35459191Skris                                        BumpPtrAllocator &Alloc,
35559191Skris                                        StringRef Filename) {
35659191Skris  StringSaver Saver(Alloc);
35759191Skris  SmallVector<StringRef, 16> Lines;
35859191Skris  auto BufOrErr = MemoryBuffer::getFile(Filename);
35959191Skris  if (!BufOrErr)
36059191Skris    return createFileError(Filename, BufOrErr.getError());
36159191Skris
36259191Skris  BufOrErr.get()->getBuffer().split(Lines, '\n');
36359191Skris  size_t NumLines = Lines.size();
36459191Skris  for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) {
36559191Skris    StringRef TrimmedLine = Lines[LineNo].split('#').first.trim();
36659191Skris    if (TrimmedLine.empty())
36759191Skris      continue;
36859191Skris
36959191Skris    std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' ');
37059191Skris    StringRef NewName = Pair.second.trim();
37159191Skris    if (NewName.empty())
37259191Skris      return createStringError(errc::invalid_argument,
37359191Skris                               "%s:%zu: missing new symbol name",
37459191Skris                               Filename.str().c_str(), LineNo + 1);
37559191Skris    SymbolsToRename.insert({Pair.first, NewName});
37659191Skris  }
37759191Skris  return Error::success();
37859191Skris}
37959191Skris
38059191Skristemplate <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
38159191Skris  T Result;
38259191Skris  if (Val.getAsInteger(0, Result))
38359191Skris    return errc::invalid_argument;
38459191Skris  return Result;
38559191Skris}
38659191Skris
38759191Skrisnamespace {
38859191Skris
38959191Skrisenum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip };
39059191Skris
39159191Skris} // anonymous namespace
39259191Skris
39359191Skrisstatic void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
39459191Skris                      ToolType Tool) {
39559191Skris  StringRef HelpText, ToolName;
39659191Skris  switch (Tool) {
39759191Skris  case ToolType::Objcopy:
39859191Skris    ToolName = "llvm-objcopy";
39959191Skris    HelpText = " [options] input [output]";
40059191Skris    break;
40159191Skris  case ToolType::Strip:
40259191Skris    ToolName = "llvm-strip";
40359191Skris    HelpText = " [options] inputs...";
40459191Skris    break;
40559191Skris  case ToolType::InstallNameTool:
40659191Skris    ToolName = "llvm-install-name-tool";
40759191Skris    HelpText = " [options] input";
40859191Skris    break;
40959191Skris  case ToolType::BitcodeStrip:
41059191Skris    ToolName = "llvm-bitcode-strip";
41159191Skris    HelpText = " [options] input";
41259191Skris    break;
41359191Skris  }
41459191Skris  OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
41559191Skris                     (ToolName + " tool").str().c_str());
41659191Skris  // TODO: Replace this with libOption call once it adds extrahelp support.
41759191Skris  // The CommandLine library has a cl::extrahelp class to support this,
41859191Skris  // but libOption does not have that yet.
41959191Skris  OS << "\nPass @FILE as argument to read options from FILE.\n";
420109998Smarkm}
421109998Smarkm
422109998Smarkmstatic Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
423109998Smarkm  // Parse value given with --add-symbol option and create the
424109998Smarkm  // new symbol if possible. The value format for --add-symbol is:
425194206Ssimon  //
426194206Ssimon  // <name>=[<section>:]<value>[,<flags>]
427194206Ssimon  //
428194206Ssimon  // where:
429109998Smarkm  // <name> - symbol name, can be empty string
430109998Smarkm  // <section> - optional section name. If not given ABS symbol is created
431109998Smarkm  // <value> - symbol value, can be decimal or hexadecimal number prefixed
432109998Smarkm  //           with 0x.
433109998Smarkm  // <flags> - optional flags affecting symbol type, binding or visibility.
434109998Smarkm  NewSymbolInfo SI;
435109998Smarkm  StringRef Value;
436109998Smarkm  std::tie(SI.SymbolName, Value) = FlagValue.split('=');
437109998Smarkm  if (Value.empty())
438162911Ssimon    return createStringError(
439162911Ssimon        errc::invalid_argument,
440162911Ssimon        "bad format for --add-symbol, missing '=' after '%s'",
441162911Ssimon        SI.SymbolName.str().c_str());
442162911Ssimon
443162911Ssimon  if (Value.contains(':')) {
444162911Ssimon    std::tie(SI.SectionName, Value) = Value.split(':');
445162911Ssimon    if (SI.SectionName.empty() || Value.empty())
446162911Ssimon      return createStringError(
447162911Ssimon          errc::invalid_argument,
448162911Ssimon          "bad format for --add-symbol, missing section name or symbol value");
449162911Ssimon  }
450162911Ssimon
451162911Ssimon  SmallVector<StringRef, 6> Flags;
452162911Ssimon  Value.split(Flags, ',');
453162911Ssimon  if (Flags[0].getAsInteger(0, SI.Value))
454162911Ssimon    return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
455162911Ssimon                             Flags[0].str().c_str());
456194206Ssimon
457194206Ssimon  using Functor = std::function<void()>;
458194206Ssimon  SmallVector<StringRef, 6> UnsupportedFlags;
459194206Ssimon  for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
460194206Ssimon    static_cast<Functor>(
461194206Ssimon        StringSwitch<Functor>(Flags[I])
462194206Ssimon            .CaseLower("global",
463194206Ssimon                       [&] { SI.Flags.push_back(SymbolFlag::Global); })
464194206Ssimon            .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); })
465194206Ssimon            .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); })
466194206Ssimon            .CaseLower("default",
467194206Ssimon                       [&] { SI.Flags.push_back(SymbolFlag::Default); })
468238405Sjkim            .CaseLower("hidden",
469238405Sjkim                       [&] { SI.Flags.push_back(SymbolFlag::Hidden); })
470238405Sjkim            .CaseLower("protected",
471238405Sjkim                       [&] { SI.Flags.push_back(SymbolFlag::Protected); })
472238405Sjkim            .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); })
473238405Sjkim            .CaseLower("section",
474238405Sjkim                       [&] { SI.Flags.push_back(SymbolFlag::Section); })
475238405Sjkim            .CaseLower("object",
476238405Sjkim                       [&] { SI.Flags.push_back(SymbolFlag::Object); })
477238405Sjkim            .CaseLower("function",
47859191Skris                       [&] { SI.Flags.push_back(SymbolFlag::Function); })
47959191Skris            .CaseLower(
48059191Skris                "indirect-function",
48159191Skris                [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); })
48259191Skris            .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); })
48359191Skris            .CaseLower("constructor",
48459191Skris                       [&] { SI.Flags.push_back(SymbolFlag::Constructor); })
48559191Skris            .CaseLower("warning",
48659191Skris                       [&] { SI.Flags.push_back(SymbolFlag::Warning); })
48759191Skris            .CaseLower("indirect",
488269686Sjkim                       [&] { SI.Flags.push_back(SymbolFlag::Indirect); })
48959191Skris            .CaseLower("synthetic",
490269686Sjkim                       [&] { SI.Flags.push_back(SymbolFlag::Synthetic); })
491269686Sjkim            .CaseLower("unique-object",
492269686Sjkim                       [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); })
493269686Sjkim            .StartsWithLower("before=",
494269686Sjkim                             [&] {
495269686Sjkim                               StringRef SymNamePart =
496269686Sjkim                                   Flags[I].split('=').second;
497269686Sjkim
498269686Sjkim                               if (!SymNamePart.empty())
499269686Sjkim                                 SI.BeforeSyms.push_back(SymNamePart);
500269686Sjkim                             })
501269686Sjkim            .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
502269686Sjkim  if (!UnsupportedFlags.empty())
503269686Sjkim    return createStringError(errc::invalid_argument,
504269686Sjkim                             "unsupported flag%s for --add-symbol: '%s'",
505269686Sjkim                             UnsupportedFlags.size() > 1 ? "s" : "",
506269686Sjkim                             join(UnsupportedFlags, "', '").c_str());
507269686Sjkim
508269686Sjkim  return SI;
509269686Sjkim}
510269686Sjkim
511269686Sjkim// Parse input option \p ArgValue and load section data. This function
512269686Sjkim// extracts section name and name of the file keeping section data from
513269686Sjkim// ArgValue, loads data from the file, and stores section name and data
514269686Sjkim// into the vector of new sections \p NewSections.
515269686Sjkimstatic Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
516269686Sjkim                                std::vector<NewSectionInfo> &NewSections) {
517269686Sjkim  if (!ArgValue.contains('='))
518269686Sjkim    return createStringError(errc::invalid_argument,
519269686Sjkim                             "bad format for " + OptionName + ": missing '='");
520269686Sjkim
521269686Sjkim  std::pair<StringRef, StringRef> SecPair = ArgValue.split("=");
522269686Sjkim  if (SecPair.second.empty())
523269686Sjkim    return createStringError(errc::invalid_argument, "bad format for " +
524269686Sjkim                                                         OptionName +
525269686Sjkim                                                         ": missing file name");
526269686Sjkim
527269686Sjkim  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
528269686Sjkim      MemoryBuffer::getFile(SecPair.second);
529269686Sjkim  if (!BufOrErr)
530269686Sjkim    return createFileError(SecPair.second,
531269686Sjkim                           errorCodeToError(BufOrErr.getError()));
532269686Sjkim
533269686Sjkim  NewSections.push_back({SecPair.first, std::move(*BufOrErr)});
534269686Sjkim  return Error::success();
535269686Sjkim}
536269686Sjkim
537269686Sjkim// parseObjcopyOptions returns the config and sets the input arguments. If a
538269686Sjkim// help flag is set then parseObjcopyOptions will print the help messege and
539269686Sjkim// exit.
540269686SjkimExpected<DriverConfig>
541269686Sjkimobjcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
542269686Sjkim                             function_ref<Error(Error)> ErrorCallback) {
543269686Sjkim  DriverConfig DC;
544269686Sjkim  ObjcopyOptTable T;
545269686Sjkim
546269686Sjkim  const char *const *DashDash =
547269686Sjkim      llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
548269686Sjkim  ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
549269686Sjkim  if (DashDash != RawArgsArr.end())
550269686Sjkim    DashDash = std::next(DashDash);
551269686Sjkim
552269686Sjkim  unsigned MissingArgumentIndex, MissingArgumentCount;
553269686Sjkim  llvm::opt::InputArgList InputArgs =
554269686Sjkim      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
555269686Sjkim
556269686Sjkim  if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
557269686Sjkim    printHelp(T, errs(), ToolType::Objcopy);
558269686Sjkim    exit(1);
559269686Sjkim  }
560269686Sjkim
561269686Sjkim  if (InputArgs.hasArg(OBJCOPY_help)) {
562269686Sjkim    printHelp(T, outs(), ToolType::Objcopy);
563269686Sjkim    exit(0);
564269686Sjkim  }
565269686Sjkim
566269686Sjkim  if (InputArgs.hasArg(OBJCOPY_version)) {
567269686Sjkim    outs() << "llvm-objcopy, compatible with GNU objcopy\n";
568269686Sjkim    cl::PrintVersionMessage();
569269686Sjkim    exit(0);
570269686Sjkim  }
571269686Sjkim
572269686Sjkim  SmallVector<const char *, 2> Positional;
573269686Sjkim
574269686Sjkim  for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
575269686Sjkim    return createStringError(errc::invalid_argument, "unknown argument '%s'",
576269686Sjkim                             Arg->getAsString(InputArgs).c_str());
577269686Sjkim
578269686Sjkim  for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
579269686Sjkim    Positional.push_back(Arg->getValue());
580269686Sjkim  std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
581269686Sjkim
582269686Sjkim  if (Positional.empty())
58359191Skris    return createStringError(errc::invalid_argument, "no input file specified");
584296317Sdelphij
585296317Sdelphij  if (Positional.size() > 2)
586296317Sdelphij    return createStringError(errc::invalid_argument,
58759191Skris                             "too many positional arguments");
588296317Sdelphij
58959191Skris  ConfigManager ConfigMgr;
59059191Skris  CommonConfig &Config = ConfigMgr.Common;
59159191Skris  COFFConfig &COFFConfig = ConfigMgr.COFF;
59259191Skris  ELFConfig &ELFConfig = ConfigMgr.ELF;
59359191Skris  MachOConfig &MachOConfig = ConfigMgr.MachO;
59459191Skris  Config.InputFilename = Positional[0];
59559191Skris  Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
59659191Skris  if (InputArgs.hasArg(OBJCOPY_target) &&
59759191Skris      (InputArgs.hasArg(OBJCOPY_input_target) ||
59859191Skris       InputArgs.hasArg(OBJCOPY_output_target)))
59959191Skris    return createStringError(
60059191Skris        errc::invalid_argument,
60159191Skris        "--target cannot be used with --input-target or --output-target");
60259191Skris
60359191Skris  if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
60459191Skris    return createStringError(errc::invalid_argument,
60559191Skris                             "--regex and --wildcard are incompatible");
60659191Skris
60759191Skris  MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
60859191Skris                                     ? MatchStyle::Regex
60959191Skris                                     : MatchStyle::Wildcard;
610269686Sjkim  MatchStyle SymbolMatchStyle
611269686Sjkim      = InputArgs.hasArg(OBJCOPY_regex)    ? MatchStyle::Regex
612269686Sjkim      : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard
613269686Sjkim                                           : MatchStyle::Literal;
614269686Sjkim  StringRef InputFormat, OutputFormat;
61559191Skris  if (InputArgs.hasArg(OBJCOPY_target)) {
61659191Skris    InputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
61759191Skris    OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
61859191Skris  } else {
619109998Smarkm    InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
620109998Smarkm    OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
621109998Smarkm  }
622109998Smarkm
623109998Smarkm  // FIXME:  Currently, we ignore the target for non-binary/ihex formats
624109998Smarkm  // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the
625109998Smarkm  // format by llvm::object::createBinary regardless of the option value.
626109998Smarkm  Config.InputFormat = StringSwitch<FileFormat>(InputFormat)
627109998Smarkm                           .Case("binary", FileFormat::Binary)
62859191Skris                           .Case("ihex", FileFormat::IHex)
62959191Skris                           .Default(FileFormat::Unspecified);
63059191Skris
63159191Skris  if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) {
632109998Smarkm    const uint8_t Invalid = 0xff;
633109998Smarkm    StringRef VisibilityStr =
634238405Sjkim        InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
635238405Sjkim
636238405Sjkim    ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr)
637109998Smarkm                                        .Case("default", ELF::STV_DEFAULT)
63859191Skris                                        .Case("hidden", ELF::STV_HIDDEN)
639                                        .Case("internal", ELF::STV_INTERNAL)
640                                        .Case("protected", ELF::STV_PROTECTED)
641                                        .Default(Invalid);
642
643    if (ELFConfig.NewSymbolVisibility == Invalid)
644      return createStringError(errc::invalid_argument,
645                               "'%s' is not a valid symbol visibility",
646                               VisibilityStr.str().c_str());
647  }
648
649  for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) {
650    StringRef Subsystem, Version;
651    std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':');
652    COFFConfig.Subsystem =
653        StringSwitch<unsigned>(Subsystem.lower())
654            .Case("boot_application",
655                  COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
656            .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
657            .Case("efi_application", COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION)
658            .Case("efi_boot_service_driver",
659                  COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
660            .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM)
661            .Case("efi_runtime_driver",
662                  COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
663            .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE)
664            .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI)
665            .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
666            .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN);
667    if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN)
668      return createStringError(errc::invalid_argument,
669                               "'%s' is not a valid subsystem",
670                               Subsystem.str().c_str());
671    if (!Version.empty()) {
672      StringRef Major, Minor;
673      std::tie(Major, Minor) = Version.split('.');
674      unsigned Number;
675      if (Major.getAsInteger(10, Number))
676        return createStringError(errc::invalid_argument,
677                                 "'%s' is not a valid subsystem major version",
678                                 Major.str().c_str());
679      COFFConfig.MajorSubsystemVersion = Number;
680      Number = 0;
681      if (!Minor.empty() && Minor.getAsInteger(10, Number))
682        return createStringError(errc::invalid_argument,
683                                 "'%s' is not a valid subsystem minor version",
684                                 Minor.str().c_str());
685      COFFConfig.MinorSubsystemVersion = Number;
686    }
687  }
688
689  Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
690                            .Case("binary", FileFormat::Binary)
691                            .Case("ihex", FileFormat::IHex)
692                            .Default(FileFormat::Unspecified);
693  if (Config.OutputFormat == FileFormat::Unspecified) {
694    if (OutputFormat.empty()) {
695      Config.OutputFormat = Config.InputFormat;
696    } else {
697      Expected<TargetInfo> Target =
698          getOutputTargetInfoByTargetName(OutputFormat);
699      if (!Target)
700        return Target.takeError();
701      Config.OutputFormat = Target->Format;
702      Config.OutputArch = Target->Machine;
703    }
704  }
705
706  if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) {
707    Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue())
708                                 .Case("zlib", DebugCompressionType::Zlib)
709                                 .Case("zstd", DebugCompressionType::Zstd)
710                                 .Default(DebugCompressionType::None);
711    if (Config.CompressionType == DebugCompressionType::None) {
712      return createStringError(
713          errc::invalid_argument,
714          "invalid or unsupported --compress-debug-sections format: %s",
715          A->getValue());
716    }
717    if (const char *Reason = compression::getReasonIfUnsupported(
718            compression::formatFor(Config.CompressionType)))
719      return createStringError(errc::invalid_argument, Reason);
720  }
721
722  Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
723  // The gnu_debuglink's target is expected to not change or else its CRC would
724  // become invalidated and get rejected. We can avoid recalculating the
725  // checksum for every target file inside an archive by precomputing the CRC
726  // here. This prevents a significant amount of I/O.
727  if (!Config.AddGnuDebugLink.empty()) {
728    auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink);
729    if (!DebugOrErr)
730      return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());
731    auto Debug = std::move(*DebugOrErr);
732    Config.GnuDebugLinkCRC32 =
733        llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
734  }
735  Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
736  Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
737  Config.AllocSectionsPrefix =
738      InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
739  if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
740    Config.ExtractPartition = Arg->getValue();
741
742  if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) {
743    if (Config.OutputFormat != FileFormat::Binary)
744      return createStringError(
745          errc::invalid_argument,
746          "'--gap-fill' is only supported for binary output");
747    ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue());
748    if (!Val)
749      return createStringError(Val.getError(), "--gap-fill: bad number: %s",
750                               A->getValue());
751    uint8_t ByteVal = Val.get();
752    if (ByteVal != Val.get())
753      return createStringError(std::errc::value_too_large,
754                               "gap-fill value %s is out of range (0 to 0xff)",
755                               A->getValue());
756    Config.GapFill = ByteVal;
757  }
758
759  if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) {
760    if (Config.OutputFormat != FileFormat::Binary)
761      return createStringError(
762          errc::invalid_argument,
763          "'--pad-to' is only supported for binary output");
764    ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue());
765    if (!Addr)
766      return createStringError(Addr.getError(), "--pad-to: bad number: %s",
767                               A->getValue());
768    Config.PadTo = *Addr;
769  }
770
771  for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
772    if (!StringRef(Arg->getValue()).contains('='))
773      return createStringError(errc::invalid_argument,
774                               "bad format for --redefine-sym");
775    auto Old2New = StringRef(Arg->getValue()).split('=');
776    if (!Config.SymbolsToRename.insert(Old2New).second)
777      return createStringError(errc::invalid_argument,
778                               "multiple redefinition of symbol '%s'",
779                               Old2New.first.str().c_str());
780  }
781
782  for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
783    if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
784                                             Arg->getValue()))
785      return std::move(E);
786
787  for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
788    Expected<SectionRename> SR =
789        parseRenameSectionValue(StringRef(Arg->getValue()));
790    if (!SR)
791      return SR.takeError();
792    if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
793      return createStringError(errc::invalid_argument,
794                               "multiple renames of section '%s'",
795                               SR->OriginalName.str().c_str());
796  }
797  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
798    Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
799        parseSetSectionAttribute("--set-section-alignment", Arg->getValue());
800    if (!NameAndAlign)
801      return NameAndAlign.takeError();
802    Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
803  }
804  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
805    Expected<SectionFlagsUpdate> SFU =
806        parseSetSectionFlagValue(Arg->getValue());
807    if (!SFU)
808      return SFU.takeError();
809    if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
810      return createStringError(
811          errc::invalid_argument,
812          "--set-section-flags set multiple times for section '%s'",
813          SFU->Name.str().c_str());
814  }
815  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) {
816    Expected<std::pair<StringRef, uint64_t>> NameAndType =
817        parseSetSectionAttribute("--set-section-type", Arg->getValue());
818    if (!NameAndType)
819      return NameAndType.takeError();
820    Config.SetSectionType[NameAndType->first] = NameAndType->second;
821  }
822  // Prohibit combinations of --set-section-{flags,type} when the section name
823  // is used as the destination of a --rename-section.
824  for (const auto &E : Config.SectionsToRename) {
825    const SectionRename &SR = E.second;
826    auto Err = [&](const char *Option) {
827      return createStringError(
828          errc::invalid_argument,
829          "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option,
830          SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
831          SR.NewName.str().c_str());
832    };
833    if (Config.SetSectionFlags.count(SR.NewName))
834      return Err("flags");
835    if (Config.SetSectionType.count(SR.NewName))
836      return Err("type");
837  }
838
839  for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section))
840    if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
841            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
842      return std::move(E);
843  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section))
844    if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
845            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
846      return std::move(E);
847  for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section))
848    if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
849            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
850      return std::move(E);
851  for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) {
852    if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section",
853                                       Config.AddSection))
854      return std::move(Err);
855  }
856  for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) {
857    if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section",
858                                       Config.UpdateSection))
859      return std::move(Err);
860  }
861  for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
862    StringRef Value(Arg->getValue());
863    if (Value.split('=').second.empty())
864      return createStringError(
865          errc::invalid_argument,
866          "bad format for --dump-section, expected section=file");
867    Config.DumpSection.push_back(Value);
868  }
869  Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
870  Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
871  Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
872  Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
873  Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
874  Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
875  Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
876  Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
877  Config.ExtractMainPartition =
878      InputArgs.hasArg(OBJCOPY_extract_main_partition);
879  ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
880  Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
881  if (auto *Arg =
882          InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
883    Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all)
884                             ? DiscardType::All
885                             : DiscardType::Locals;
886  }
887  Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
888  ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
889  MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
890  Config.DecompressDebugSections =
891      InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
892  if (Config.DiscardMode == DiscardType::All) {
893    Config.StripDebug = true;
894    ELFConfig.KeepFileSymbols = true;
895  }
896  for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
897    if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
898            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
899      return std::move(E);
900  for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
901    if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
902                                     Arg->getValue(), SymbolMatchStyle,
903                                     ErrorCallback))
904      return std::move(E);
905  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
906    if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
907            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
908      return std::move(E);
909  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
910    if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
911                                     Arg->getValue(), SymbolMatchStyle,
912                                     ErrorCallback))
913      return std::move(E);
914  for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
915    if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
916            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
917      return std::move(E);
918  for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
919    if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
920                                     Arg->getValue(), SymbolMatchStyle,
921                                     ErrorCallback))
922      return std::move(E);
923  for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
924    if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
925            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
926      return std::move(E);
927  for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
928    if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
929                                     Arg->getValue(), SymbolMatchStyle,
930                                     ErrorCallback))
931      return std::move(E);
932  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
933    if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
934            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
935      return std::move(E);
936  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
937    if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
938                                     Arg->getValue(), SymbolMatchStyle,
939                                     ErrorCallback))
940      return std::move(E);
941  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
942    if (Error E =
943            Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
944                Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
945      return std::move(E);
946  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
947    if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
948                                     Arg->getValue(), SymbolMatchStyle,
949                                     ErrorCallback))
950      return std::move(E);
951  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
952    if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
953            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
954      return std::move(E);
955  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
956    if (Error E =
957            addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
958                               SymbolMatchStyle, ErrorCallback))
959      return std::move(E);
960  for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
961    Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
962    if (!SymInfo)
963      return SymInfo.takeError();
964
965    Config.SymbolsToAdd.push_back(*SymInfo);
966  }
967
968  ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
969
970  Config.DeterministicArchives = InputArgs.hasFlag(
971      OBJCOPY_enable_deterministic_archives,
972      OBJCOPY_disable_deterministic_archives, /*default=*/true);
973
974  Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
975
976  if (Config.PreserveDates &&
977      (Config.OutputFilename == "-" || Config.InputFilename == "-"))
978    return createStringError(errc::invalid_argument,
979                             "--preserve-dates requires a file");
980
981  for (auto *Arg : InputArgs)
982    if (Arg->getOption().matches(OBJCOPY_set_start)) {
983      auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
984      if (!EAddr)
985        return createStringError(
986            EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
987
988      ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
989    } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
990      auto EIncr = getAsInteger<int64_t>(Arg->getValue());
991      if (!EIncr)
992        return createStringError(EIncr.getError(),
993                                 "bad entry point increment: '%s'",
994                                 Arg->getValue());
995      auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr)
996                                      : [](uint64_t A) { return A; };
997      ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
998        return Expr(EAddr) + *EIncr;
999      };
1000    }
1001
1002  if (Config.DecompressDebugSections &&
1003      Config.CompressionType != DebugCompressionType::None) {
1004    return createStringError(
1005        errc::invalid_argument,
1006        "cannot specify both --compress-debug-sections and "
1007        "--decompress-debug-sections");
1008  }
1009
1010  if (Config.ExtractPartition && Config.ExtractMainPartition)
1011    return createStringError(errc::invalid_argument,
1012                             "cannot specify --extract-partition together with "
1013                             "--extract-main-partition");
1014
1015  DC.CopyConfigs.push_back(std::move(ConfigMgr));
1016  return std::move(DC);
1017}
1018
1019// parseInstallNameToolOptions returns the config and sets the input arguments.
1020// If a help flag is set then parseInstallNameToolOptions will print the help
1021// messege and exit.
1022Expected<DriverConfig>
1023objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
1024  DriverConfig DC;
1025  ConfigManager ConfigMgr;
1026  CommonConfig &Config = ConfigMgr.Common;
1027  MachOConfig &MachOConfig = ConfigMgr.MachO;
1028  InstallNameToolOptTable T;
1029  unsigned MissingArgumentIndex, MissingArgumentCount;
1030  llvm::opt::InputArgList InputArgs =
1031      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1032
1033  if (MissingArgumentCount)
1034    return createStringError(
1035        errc::invalid_argument,
1036        "missing argument to " +
1037            StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
1038            " option");
1039
1040  if (InputArgs.size() == 0) {
1041    printHelp(T, errs(), ToolType::InstallNameTool);
1042    exit(1);
1043  }
1044
1045  if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
1046    printHelp(T, outs(), ToolType::InstallNameTool);
1047    exit(0);
1048  }
1049
1050  if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
1051    outs() << "llvm-install-name-tool, compatible with cctools "
1052              "install_name_tool\n";
1053    cl::PrintVersionMessage();
1054    exit(0);
1055  }
1056
1057  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
1058    MachOConfig.RPathToAdd.push_back(Arg->getValue());
1059
1060  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
1061    MachOConfig.RPathToPrepend.push_back(Arg->getValue());
1062
1063  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
1064    StringRef RPath = Arg->getValue();
1065
1066    // Cannot add and delete the same rpath at the same time.
1067    if (is_contained(MachOConfig.RPathToAdd, RPath))
1068      return createStringError(
1069          errc::invalid_argument,
1070          "cannot specify both -add_rpath '%s' and -delete_rpath '%s'",
1071          RPath.str().c_str(), RPath.str().c_str());
1072    if (is_contained(MachOConfig.RPathToPrepend, RPath))
1073      return createStringError(
1074          errc::invalid_argument,
1075          "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'",
1076          RPath.str().c_str(), RPath.str().c_str());
1077
1078    MachOConfig.RPathsToRemove.insert(RPath);
1079  }
1080
1081  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) {
1082    StringRef Old = Arg->getValue(0);
1083    StringRef New = Arg->getValue(1);
1084
1085    auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; };
1086
1087    // Cannot specify duplicate -rpath entries
1088    auto It1 = find_if(
1089        MachOConfig.RPathsToUpdate,
1090        [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) {
1091          return Match(OldNew.getFirst()) || Match(OldNew.getSecond());
1092        });
1093    if (It1 != MachOConfig.RPathsToUpdate.end())
1094      return createStringError(errc::invalid_argument,
1095                               "cannot specify both -rpath '" +
1096                                   It1->getFirst() + "' '" + It1->getSecond() +
1097                                   "' and -rpath '" + Old + "' '" + New + "'");
1098
1099    // Cannot specify the same rpath under both -delete_rpath and -rpath
1100    auto It2 = find_if(MachOConfig.RPathsToRemove, Match);
1101    if (It2 != MachOConfig.RPathsToRemove.end())
1102      return createStringError(errc::invalid_argument,
1103                               "cannot specify both -delete_rpath '" + *It2 +
1104                                   "' and -rpath '" + Old + "' '" + New + "'");
1105
1106    // Cannot specify the same rpath under both -add_rpath and -rpath
1107    auto It3 = find_if(MachOConfig.RPathToAdd, Match);
1108    if (It3 != MachOConfig.RPathToAdd.end())
1109      return createStringError(errc::invalid_argument,
1110                               "cannot specify both -add_rpath '" + *It3 +
1111                                   "' and -rpath '" + Old + "' '" + New + "'");
1112
1113    // Cannot specify the same rpath under both -prepend_rpath and -rpath.
1114    auto It4 = find_if(MachOConfig.RPathToPrepend, Match);
1115    if (It4 != MachOConfig.RPathToPrepend.end())
1116      return createStringError(errc::invalid_argument,
1117                               "cannot specify both -prepend_rpath '" + *It4 +
1118                                   "' and -rpath '" + Old + "' '" + New + "'");
1119
1120    MachOConfig.RPathsToUpdate.insert({Old, New});
1121  }
1122
1123  if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) {
1124    MachOConfig.SharedLibId = Arg->getValue();
1125    if (MachOConfig.SharedLibId->empty())
1126      return createStringError(errc::invalid_argument,
1127                               "cannot specify an empty id");
1128  }
1129
1130  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change))
1131    MachOConfig.InstallNamesToUpdate.insert(
1132        {Arg->getValue(0), Arg->getValue(1)});
1133
1134  MachOConfig.RemoveAllRpaths =
1135      InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);
1136
1137  SmallVector<StringRef, 2> Positional;
1138  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
1139    return createStringError(errc::invalid_argument, "unknown argument '%s'",
1140                             Arg->getAsString(InputArgs).c_str());
1141  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
1142    Positional.push_back(Arg->getValue());
1143  if (Positional.empty())
1144    return createStringError(errc::invalid_argument, "no input file specified");
1145  if (Positional.size() > 1)
1146    return createStringError(
1147        errc::invalid_argument,
1148        "llvm-install-name-tool expects a single input file");
1149  Config.InputFilename = Positional[0];
1150  Config.OutputFilename = Positional[0];
1151
1152  DC.CopyConfigs.push_back(std::move(ConfigMgr));
1153  return std::move(DC);
1154}
1155
1156Expected<DriverConfig>
1157objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
1158                                  function_ref<Error(Error)> ErrorCallback) {
1159  DriverConfig DC;
1160  ConfigManager ConfigMgr;
1161  CommonConfig &Config = ConfigMgr.Common;
1162  MachOConfig &MachOConfig = ConfigMgr.MachO;
1163  BitcodeStripOptTable T;
1164  unsigned MissingArgumentIndex, MissingArgumentCount;
1165  opt::InputArgList InputArgs =
1166      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1167
1168  if (InputArgs.size() == 0) {
1169    printHelp(T, errs(), ToolType::BitcodeStrip);
1170    exit(1);
1171  }
1172
1173  if (InputArgs.hasArg(BITCODE_STRIP_help)) {
1174    printHelp(T, outs(), ToolType::BitcodeStrip);
1175    exit(0);
1176  }
1177
1178  if (InputArgs.hasArg(BITCODE_STRIP_version)) {
1179    outs() << "llvm-bitcode-strip, compatible with cctools "
1180              "bitcode_strip\n";
1181    cl::PrintVersionMessage();
1182    exit(0);
1183  }
1184
1185  for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN))
1186    return createStringError(errc::invalid_argument, "unknown argument '%s'",
1187                             Arg->getAsString(InputArgs).c_str());
1188
1189  SmallVector<StringRef, 2> Positional;
1190  for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
1191    Positional.push_back(Arg->getValue());
1192  if (Positional.size() > 1)
1193    return createStringError(errc::invalid_argument,
1194                             "llvm-bitcode-strip expects a single input file");
1195  assert(!Positional.empty());
1196  Config.InputFilename = Positional[0];
1197
1198  if (!InputArgs.hasArg(BITCODE_STRIP_output)) {
1199    return createStringError(errc::invalid_argument,
1200                             "-o is a required argument");
1201  }
1202  Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output);
1203
1204  if (!InputArgs.hasArg(BITCODE_STRIP_remove))
1205    return createStringError(errc::invalid_argument, "no action specified");
1206
1207  // We only support -r for now, which removes all bitcode sections and
1208  // the __LLVM segment if it's now empty.
1209  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1210      "__LLVM,__asm", MatchStyle::Literal, ErrorCallback)));
1211  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1212      "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback)));
1213  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1214      "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback)));
1215  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1216      "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback)));
1217  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1218      "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback)));
1219  MachOConfig.EmptySegmentsToRemove.insert("__LLVM");
1220
1221  DC.CopyConfigs.push_back(std::move(ConfigMgr));
1222  return std::move(DC);
1223}
1224
1225// parseStripOptions returns the config and sets the input arguments. If a
1226// help flag is set then parseStripOptions will print the help messege and
1227// exit.
1228Expected<DriverConfig>
1229objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
1230                           function_ref<Error(Error)> ErrorCallback) {
1231  const char *const *DashDash =
1232      llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
1233  ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
1234  if (DashDash != RawArgsArr.end())
1235    DashDash = std::next(DashDash);
1236
1237  StripOptTable T;
1238  unsigned MissingArgumentIndex, MissingArgumentCount;
1239  llvm::opt::InputArgList InputArgs =
1240      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1241
1242  if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
1243    printHelp(T, errs(), ToolType::Strip);
1244    exit(1);
1245  }
1246
1247  if (InputArgs.hasArg(STRIP_help)) {
1248    printHelp(T, outs(), ToolType::Strip);
1249    exit(0);
1250  }
1251
1252  if (InputArgs.hasArg(STRIP_version)) {
1253    outs() << "llvm-strip, compatible with GNU strip\n";
1254    cl::PrintVersionMessage();
1255    exit(0);
1256  }
1257
1258  SmallVector<StringRef, 2> Positional;
1259  for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
1260    return createStringError(errc::invalid_argument, "unknown argument '%s'",
1261                             Arg->getAsString(InputArgs).c_str());
1262  for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
1263    Positional.push_back(Arg->getValue());
1264  std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
1265
1266  if (Positional.empty())
1267    return createStringError(errc::invalid_argument, "no input file specified");
1268
1269  if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
1270    return createStringError(
1271        errc::invalid_argument,
1272        "multiple input files cannot be used in combination with -o");
1273
1274  ConfigManager ConfigMgr;
1275  CommonConfig &Config = ConfigMgr.Common;
1276  ELFConfig &ELFConfig = ConfigMgr.ELF;
1277  MachOConfig &MachOConfig = ConfigMgr.MachO;
1278
1279  if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
1280    return createStringError(errc::invalid_argument,
1281                             "--regex and --wildcard are incompatible");
1282  MatchStyle SectionMatchStyle =
1283      InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
1284  MatchStyle SymbolMatchStyle
1285      = InputArgs.hasArg(STRIP_regex)    ? MatchStyle::Regex
1286      : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard
1287                                         : MatchStyle::Literal;
1288  ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
1289  Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
1290
1291  if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals))
1292    Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all)
1293                             ? DiscardType::All
1294                             : DiscardType::Locals;
1295  Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
1296  Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
1297  if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
1298    Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
1299  Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
1300  MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
1301  Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
1302  ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
1303  MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
1304
1305  for (auto *Arg : InputArgs.filtered(STRIP_keep_section))
1306    if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
1307            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1308      return std::move(E);
1309
1310  for (auto *Arg : InputArgs.filtered(STRIP_remove_section))
1311    if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
1312            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1313      return std::move(E);
1314
1315  for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol))
1316    if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
1317            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1318      return std::move(E);
1319
1320  for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol))
1321    if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
1322            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1323      return std::move(E);
1324
1325  if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
1326      !Config.OnlyKeepDebug && !Config.StripUnneeded &&
1327      Config.DiscardMode == DiscardType::None && !Config.StripAllGNU &&
1328      Config.SymbolsToRemove.empty())
1329    Config.StripAll = true;
1330
1331  if (Config.DiscardMode == DiscardType::All) {
1332    Config.StripDebug = true;
1333    ELFConfig.KeepFileSymbols = true;
1334  }
1335
1336  Config.DeterministicArchives =
1337      InputArgs.hasFlag(STRIP_enable_deterministic_archives,
1338                        STRIP_disable_deterministic_archives, /*default=*/true);
1339
1340  Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
1341  Config.InputFormat = FileFormat::Unspecified;
1342  Config.OutputFormat = FileFormat::Unspecified;
1343
1344  DriverConfig DC;
1345  if (Positional.size() == 1) {
1346    Config.InputFilename = Positional[0];
1347    Config.OutputFilename =
1348        InputArgs.getLastArgValue(STRIP_output, Positional[0]);
1349    DC.CopyConfigs.push_back(std::move(ConfigMgr));
1350  } else {
1351    StringMap<unsigned> InputFiles;
1352    for (StringRef Filename : Positional) {
1353      if (InputFiles[Filename]++ == 1) {
1354        if (Filename == "-")
1355          return createStringError(
1356              errc::invalid_argument,
1357              "cannot specify '-' as an input file more than once");
1358        if (Error E = ErrorCallback(createStringError(
1359                errc::invalid_argument, "'%s' was already specified",
1360                Filename.str().c_str())))
1361          return std::move(E);
1362      }
1363      Config.InputFilename = Filename;
1364      Config.OutputFilename = Filename;
1365      DC.CopyConfigs.push_back(ConfigMgr);
1366    }
1367  }
1368
1369  if (Config.PreserveDates && (is_contained(Positional, "-") ||
1370                               InputArgs.getLastArgValue(STRIP_output) == "-"))
1371    return createStringError(errc::invalid_argument,
1372                             "--preserve-dates requires a file");
1373
1374  return std::move(DC);
1375}
1376