//===- ObjcopyOptions.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ObjcopyOptions.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/ObjCopy/CommonConfig.h"
#include "llvm/ObjCopy/ConfigManager.h"
#include "llvm/ObjCopy/MachO/MachOConfig.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/OffloadBundle.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"

using namespace llvm;
using namespace llvm::objcopy;
using namespace llvm::object;
using namespace llvm::opt;

namespace {
enum ObjcopyID {
  OBJCOPY_INVALID = 0, // This is not an option ID.
#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
#include "ObjcopyOpts.inc"
#undef OPTION
};

namespace objcopy_opt {
#define OPTTABLE_STR_TABLE_CODE
#include "ObjcopyOpts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "ObjcopyOpts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

static constexpr opt::OptTable::Info ObjcopyInfoTable[] = {
#define OPTION(...)                                                            \
  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
#include "ObjcopyOpts.inc"
#undef OPTION
};
} // namespace objcopy_opt

class ObjcopyOptTable : public opt::GenericOptTable {
public:
  ObjcopyOptTable()
      : opt::GenericOptTable(objcopy_opt::OptionStrTable,
                             objcopy_opt::OptionPrefixesTable,
                             objcopy_opt::ObjcopyInfoTable) {
    setGroupedShortOptions(true);
    setDashDashParsing(true);
  }
};

enum InstallNameToolID {
  INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
#define OPTION(...)                                                            \
  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
#include "InstallNameToolOpts.inc"
#undef OPTION
};

namespace install_name_tool {
#define OPTTABLE_STR_TABLE_CODE
#include "InstallNameToolOpts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "InstallNameToolOpts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = {
#define OPTION(...)                                                            \
  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
#include "InstallNameToolOpts.inc"
#undef OPTION
};
} // namespace install_name_tool

class InstallNameToolOptTable : public opt::GenericOptTable {
public:
  InstallNameToolOptTable()
      : GenericOptTable(install_name_tool::OptionStrTable,
                        install_name_tool::OptionPrefixesTable,
                        install_name_tool::InstallNameToolInfoTable) {}
};

enum BitcodeStripID {
  BITCODE_STRIP_INVALID = 0, // This is not an option ID.
#define OPTION(...)                                                            \
  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
#include "BitcodeStripOpts.inc"
#undef OPTION
};

namespace bitcode_strip {
#define OPTTABLE_STR_TABLE_CODE
#include "BitcodeStripOpts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "BitcodeStripOpts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = {
#define OPTION(...)                                                            \
  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
#include "BitcodeStripOpts.inc"
#undef OPTION
};
} // namespace bitcode_strip

class BitcodeStripOptTable : public opt::GenericOptTable {
public:
  BitcodeStripOptTable()
      : opt::GenericOptTable(bitcode_strip::OptionStrTable,
                             bitcode_strip::OptionPrefixesTable,
                             bitcode_strip::BitcodeStripInfoTable) {}
};

enum StripID {
  STRIP_INVALID = 0, // This is not an option ID.
#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
#include "StripOpts.inc"
#undef OPTION
};

namespace strip {
#define OPTTABLE_STR_TABLE_CODE
#include "StripOpts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "StripOpts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

static constexpr opt::OptTable::Info StripInfoTable[] = {
#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
#include "StripOpts.inc"
#undef OPTION
};
} // namespace strip

class StripOptTable : public opt::GenericOptTable {
public:
  StripOptTable()
      : GenericOptTable(strip::OptionStrTable, strip::OptionPrefixesTable,
                        strip::StripInfoTable) {
    setGroupedShortOptions(true);
  }
};

enum ExtractBundleEntryID {
  EXTRACT_BUNDLE_ENTRY_INVALID = 0, // This is not an option ID.
#define OPTION(...)                                                            \
  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(EXTRACT_BUNDLE_ENTRY_, __VA_ARGS__),
#include "ExtractBundleEntryOpts.inc"
#undef OPTION
};

namespace extract_bundle_entry {
#define OPTTABLE_STR_TABLE_CODE
#include "ExtractBundleEntryOpts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "ExtractBundleEntryOpts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

static constexpr opt::OptTable::Info ExtractBundleEntryInfoTable[] = {
#define OPTION(...)                                                            \
  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(EXTRACT_BUNDLE_ENTRY_, __VA_ARGS__),
#include "ExtractBundleEntryOpts.inc"
#undef OPTION
};
} // namespace extract_bundle_entry

class ExtractBundleEntryOptTable : public opt::GenericOptTable {
public:
  ExtractBundleEntryOptTable()
      : GenericOptTable(extract_bundle_entry::OptionStrTable,
                        extract_bundle_entry::OptionPrefixesTable,
                        extract_bundle_entry::ExtractBundleEntryInfoTable) {
    setGroupedShortOptions(true);
  }
};

} // namespace

static SectionFlag parseSectionRenameFlag(StringRef SectionName) {
  return llvm::StringSwitch<SectionFlag>(SectionName)
      .CaseLower("alloc", SectionFlag::SecAlloc)
      .CaseLower("load", SectionFlag::SecLoad)
      .CaseLower("noload", SectionFlag::SecNoload)
      .CaseLower("readonly", SectionFlag::SecReadonly)
      .CaseLower("debug", SectionFlag::SecDebug)
      .CaseLower("code", SectionFlag::SecCode)
      .CaseLower("data", SectionFlag::SecData)
      .CaseLower("rom", SectionFlag::SecRom)
      .CaseLower("merge", SectionFlag::SecMerge)
      .CaseLower("strings", SectionFlag::SecStrings)
      .CaseLower("contents", SectionFlag::SecContents)
      .CaseLower("share", SectionFlag::SecShare)
      .CaseLower("exclude", SectionFlag::SecExclude)
      .CaseLower("large", SectionFlag::SecLarge)
      .Default(SectionFlag::SecNone);
}

static Expected<SectionFlag>
parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
  SectionFlag ParsedFlags = SectionFlag::SecNone;
  for (StringRef Flag : SectionFlags) {
    SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
    if (ParsedFlag == SectionFlag::SecNone)
      return createStringError(
          errc::invalid_argument,
          "unrecognized section flag '%s'. Flags supported for GNU "
          "compatibility: alloc, load, noload, readonly, exclude, debug, "
          "code, data, rom, share, contents, merge, strings, large",
          Flag.str().c_str());
    ParsedFlags |= ParsedFlag;
  }

  return ParsedFlags;
}

static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {
  if (!FlagValue.contains('='))
    return createStringError(errc::invalid_argument,
                             "bad format for --rename-section: missing '='");

  // Initial split: ".foo" = ".bar,f1,f2,..."
  auto Old2New = FlagValue.split('=');
  SectionRename SR;
  SR.OriginalName = Old2New.first;

  // Flags split: ".bar" "f1" "f2" ...
  SmallVector<StringRef, 6> NameAndFlags;
  Old2New.second.split(NameAndFlags, ',');
  SR.NewName = NameAndFlags[0];

  if (NameAndFlags.size() > 1) {
    Expected<SectionFlag> ParsedFlagSet =
        parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front());
    if (!ParsedFlagSet)
      return ParsedFlagSet.takeError();
    SR.NewFlags = *ParsedFlagSet;
  }

  return SR;
}

static Expected<std::pair<StringRef, uint64_t>>
parseSetSectionAttribute(StringRef Option, StringRef FlagValue) {
  if (!FlagValue.contains('='))
    return make_error<StringError>("bad format for " + Option + ": missing '='",
                                   errc::invalid_argument);
  auto Split = StringRef(FlagValue).split('=');
  if (Split.first.empty())
    return make_error<StringError>("bad format for " + Option +
                                       ": missing section name",
                                   errc::invalid_argument);
  uint64_t Value;
  if (Split.second.getAsInteger(0, Value))
    return make_error<StringError>("invalid value for " + Option + ": '" +
                                       Split.second + "'",
                                   errc::invalid_argument);
  return std::make_pair(Split.first, Value);
}

static Expected<SectionFlagsUpdate>
parseSetSectionFlagValue(StringRef FlagValue) {
  if (!StringRef(FlagValue).contains('='))
    return createStringError(errc::invalid_argument,
                             "bad format for --set-section-flags: missing '='");

  // Initial split: ".foo" = "f1,f2,..."
  auto Section2Flags = StringRef(FlagValue).split('=');
  SectionFlagsUpdate SFU;
  SFU.Name = Section2Flags.first;

  // Flags split: "f1" "f2" ...
  SmallVector<StringRef, 6> SectionFlags;
  Section2Flags.second.split(SectionFlags, ',');
  Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags);
  if (!ParsedFlagSet)
    return ParsedFlagSet.takeError();
  SFU.NewFlags = *ParsedFlagSet;

  return SFU;
}

static Expected<uint8_t> parseVisibilityType(StringRef VisType) {
  const uint8_t Invalid = 0xff;
  uint8_t type = StringSwitch<uint8_t>(VisType)
                     .Case("default", ELF::STV_DEFAULT)
                     .Case("hidden", ELF::STV_HIDDEN)
                     .Case("internal", ELF::STV_INTERNAL)
                     .Case("protected", ELF::STV_PROTECTED)
                     .Default(Invalid);
  if (type == Invalid)
    return createStringError(errc::invalid_argument,
                             "'%s' is not a valid symbol visibility",
                             VisType.str().c_str());
  return type;
}

namespace {
struct TargetInfo {
  FileFormat Format;
  MachineInfo Machine;
};
} // namespace

// FIXME: consolidate with the bfd parsing used by lld.
static const StringMap<MachineInfo> TargetMap{
    // Name, {EMachine, 64bit, LittleEndian}
    // x86
    {"elf32-i386", {ELF::EM_386, false, true}},
    {"elf32-x86-64", {ELF::EM_X86_64, false, true}},
    {"elf64-x86-64", {ELF::EM_X86_64, true, true}},
    // Intel MCU
    {"elf32-iamcu", {ELF::EM_IAMCU, false, true}},
    // ARM
    {"elf32-littlearm", {ELF::EM_ARM, false, true}},
    // ARM AArch64
    {"elf64-aarch64", {ELF::EM_AARCH64, true, true}},
    {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}},
    // RISC-V
    {"elf32-littleriscv", {ELF::EM_RISCV, false, true}},
    {"elf64-littleriscv", {ELF::EM_RISCV, true, true}},
    {"elf32-bigriscv", {ELF::EM_RISCV, false, false}},
    {"elf64-bigriscv", {ELF::EM_RISCV, true, false}},
    // PowerPC
    {"elf32-powerpc", {ELF::EM_PPC, false, false}},
    {"elf32-powerpcle", {ELF::EM_PPC, false, true}},
    {"elf64-powerpc", {ELF::EM_PPC64, true, false}},
    {"elf64-powerpcle", {ELF::EM_PPC64, true, true}},
    // MIPS
    {"elf32-bigmips", {ELF::EM_MIPS, false, false}},
    {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}},
    {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}},
    {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}},
    {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}},
    {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}},
    {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}},
    // SPARC
    {"elf32-sparc", {ELF::EM_SPARC, false, false}},
    {"elf32-sparcel", {ELF::EM_SPARC, false, true}},
    // Hexagon
    {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}},
    // LoongArch
    {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}},
    {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}},
    // SystemZ
    {"elf64-s390", {ELF::EM_S390, true, false}},
    // AMDGPU
    {"elf64-amdgpu", {ELF::EM_AMDGPU, true, true}},
};

static Expected<TargetInfo>
getOutputTargetInfoByTargetName(StringRef TargetName) {
  StringRef OriginalTargetName = TargetName;
  bool IsFreeBSD = TargetName.consume_back("-freebsd");
  auto Iter = TargetMap.find(TargetName);
  if (Iter == std::end(TargetMap))
    return createStringError(errc::invalid_argument,
                             "invalid output format: '%s'",
                             OriginalTargetName.str().c_str());
  MachineInfo MI = Iter->getValue();
  if (IsFreeBSD)
    MI.OSABI = ELF::ELFOSABI_FREEBSD;

  FileFormat Format;
  if (TargetName.starts_with("elf"))
    Format = FileFormat::ELF;
  else
    // This should never happen because `TargetName` is valid (it certainly
    // exists in the TargetMap).
    llvm_unreachable("unknown target prefix");

  return {TargetInfo{Format, MI}};
}

static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
                                StringRef Filename, MatchStyle MS,
                                function_ref<Error(Error)> ErrorCallback) {
  StringSaver Saver(Alloc);
  SmallVector<StringRef, 16> Lines;
  auto BufOrErr = MemoryBuffer::getFile(Filename);
  if (!BufOrErr)
    return createFileError(Filename, BufOrErr.getError());

  BufOrErr.get()->getBuffer().split(Lines, '\n');
  for (StringRef Line : Lines) {
    // Ignore everything after '#', trim whitespace, and only add the symbol if
    // it's not empty.
    auto TrimmedLine = Line.split('#').first.trim();
    if (!TrimmedLine.empty())
      if (Error E = Symbols.addMatcher(NameOrPattern::create(
              Saver.save(TrimmedLine), MS, ErrorCallback)))
        return E;
  }

  return Error::success();
}

static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
                                        BumpPtrAllocator &Alloc,
                                        StringRef Filename) {
  StringSaver Saver(Alloc);
  SmallVector<StringRef, 16> Lines;
  auto BufOrErr = MemoryBuffer::getFile(Filename);
  if (!BufOrErr)
    return createFileError(Filename, BufOrErr.getError());

  BufOrErr.get()->getBuffer().split(Lines, '\n');
  size_t NumLines = Lines.size();
  for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) {
    StringRef TrimmedLine = Lines[LineNo].split('#').first.trim();
    if (TrimmedLine.empty())
      continue;

    std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' ');
    StringRef NewName = Pair.second.trim();
    if (NewName.empty())
      return createStringError(errc::invalid_argument,
                               "%s:%zu: missing new symbol name",
                               Filename.str().c_str(), LineNo + 1);
    SymbolsToRename.insert({Pair.first, NewName});
  }
  return Error::success();
}

template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
  T Result;
  if (Val.getAsInteger(0, Result))
    return errc::invalid_argument;
  return Result;
}

namespace {

enum class ToolType {
  Objcopy,
  Strip,
  InstallNameTool,
  BitcodeStrip,
  ExtractBundleEntry
};

} // anonymous namespace

static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
                      ToolType Tool) {
  StringRef HelpText, ToolName;
  switch (Tool) {
  case ToolType::Objcopy:
    ToolName = "llvm-objcopy";
    HelpText = " [options] input [output]";
    break;
  case ToolType::Strip:
    ToolName = "llvm-strip";
    HelpText = " [options] inputs...";
    break;
  case ToolType::InstallNameTool:
    ToolName = "llvm-install-name-tool";
    HelpText = " [options] input";
    break;
  case ToolType::BitcodeStrip:
    ToolName = "llvm-bitcode-strip";
    HelpText = " [options] input";
    break;
  case ToolType::ExtractBundleEntry:
    ToolName = "llvm-extract-bundle-entry";
    HelpText = " URI";
    break;
  }
  OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
                     (ToolName + " tool").str().c_str());
  // TODO: Replace this with libOption call once it adds extrahelp support.
  // The CommandLine library has a cl::extrahelp class to support this,
  // but libOption does not have that yet.
  OS << "\nPass @FILE as argument to read options from FILE.\n";
}

static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
  // Parse value given with --add-symbol option and create the
  // new symbol if possible. The value format for --add-symbol is:
  //
  // <name>=[<section>:]<value>[,<flags>]
  //
  // where:
  // <name> - symbol name, can be empty string
  // <section> - optional section name. If not given ABS symbol is created
  // <value> - symbol value, can be decimal or hexadecimal number prefixed
  //           with 0x.
  // <flags> - optional flags affecting symbol type, binding or visibility.
  NewSymbolInfo SI;
  StringRef Value;
  std::tie(SI.SymbolName, Value) = FlagValue.split('=');
  if (Value.empty())
    return createStringError(
        errc::invalid_argument,
        "bad format for --add-symbol, missing '=' after '%s'",
        SI.SymbolName.str().c_str());

  if (Value.contains(':')) {
    std::tie(SI.SectionName, Value) = Value.split(':');
    if (SI.SectionName.empty() || Value.empty())
      return createStringError(
          errc::invalid_argument,
          "bad format for --add-symbol, missing section name or symbol value");
  }

  SmallVector<StringRef, 6> Flags;
  Value.split(Flags, ',');
  if (Flags[0].getAsInteger(0, SI.Value))
    return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
                             Flags[0].str().c_str());

  using Functor = std::function<void()>;
  SmallVector<StringRef, 6> UnsupportedFlags;
  for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
    static_cast<Functor>(
        StringSwitch<Functor>(Flags[I])
            .CaseLower("global",
                       [&] { SI.Flags.push_back(SymbolFlag::Global); })
            .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); })
            .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); })
            .CaseLower("default",
                       [&] { SI.Flags.push_back(SymbolFlag::Default); })
            .CaseLower("hidden",
                       [&] { SI.Flags.push_back(SymbolFlag::Hidden); })
            .CaseLower("protected",
                       [&] { SI.Flags.push_back(SymbolFlag::Protected); })
            .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); })
            .CaseLower("section",
                       [&] { SI.Flags.push_back(SymbolFlag::Section); })
            .CaseLower("object",
                       [&] { SI.Flags.push_back(SymbolFlag::Object); })
            .CaseLower("function",
                       [&] { SI.Flags.push_back(SymbolFlag::Function); })
            .CaseLower(
                "indirect-function",
                [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); })
            .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); })
            .CaseLower("constructor",
                       [&] { SI.Flags.push_back(SymbolFlag::Constructor); })
            .CaseLower("warning",
                       [&] { SI.Flags.push_back(SymbolFlag::Warning); })
            .CaseLower("indirect",
                       [&] { SI.Flags.push_back(SymbolFlag::Indirect); })
            .CaseLower("synthetic",
                       [&] { SI.Flags.push_back(SymbolFlag::Synthetic); })
            .CaseLower("unique-object",
                       [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); })
            .StartsWithLower("before=",
                             [&] {
                               StringRef SymNamePart =
                                   Flags[I].split('=').second;

                               if (!SymNamePart.empty())
                                 SI.BeforeSyms.push_back(SymNamePart);
                             })
            .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
  if (!UnsupportedFlags.empty())
    return createStringError(errc::invalid_argument,
                             "unsupported flag%s for --add-symbol: '%s'",
                             UnsupportedFlags.size() > 1 ? "s" : "",
                             join(UnsupportedFlags, "', '").c_str());

  return SI;
}

static Expected<RemoveNoteInfo> parseRemoveNoteInfo(StringRef FlagValue) {
  // Parse value given with --remove-note option. The format is:
  //
  // [name/]type_id
  //
  // where:
  // <name>    - optional note name. If not given, all notes with the specified
  //             <type_id> are removed.
  // <type_id> - note type value, can be decimal or hexadecimal number prefixed
  //             with 0x.
  RemoveNoteInfo NI;
  StringRef TypeIdStr;
  if (auto Idx = FlagValue.find('/'); Idx != StringRef::npos) {
    if (Idx == 0)
      return createStringError(
          errc::invalid_argument,
          "bad format for --remove-note, note name is empty");
    NI.Name = FlagValue.slice(0, Idx);
    TypeIdStr = FlagValue.substr(Idx + 1);
  } else {
    TypeIdStr = FlagValue;
  }
  if (TypeIdStr.empty())
    return createStringError(errc::invalid_argument,
                             "bad format for --remove-note, missing type_id");
  if (TypeIdStr.getAsInteger(0, NI.TypeId))
    return createStringError(errc::invalid_argument,
                             "bad note type_id for --remove-note: '%s'",
                             TypeIdStr.str().c_str());
  return NI;
}

// Parse input option \p ArgValue and load section data. This function
// extracts section name and name of the file keeping section data from
// ArgValue, loads data from the file, and stores section name and data
// into the vector of new sections \p NewSections.
static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
                                SmallVector<NewSectionInfo, 0> &NewSections) {
  if (!ArgValue.contains('='))
    return createStringError(errc::invalid_argument,
                             "bad format for " + OptionName + ": missing '='");

  std::pair<StringRef, StringRef> SecPair = ArgValue.split("=");
  if (SecPair.second.empty())
    return createStringError(errc::invalid_argument, "bad format for " +
                                                         OptionName +
                                                         ": missing file name");

  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
      MemoryBuffer::getFile(SecPair.second);
  if (!BufOrErr)
    return createFileError(SecPair.second,
                           errorCodeToError(BufOrErr.getError()));

  NewSections.push_back({SecPair.first, std::move(*BufOrErr)});
  return Error::success();
}

static Expected<int64_t> parseChangeSectionLMA(StringRef ArgValue,
                                               StringRef OptionName) {
  StringRef StringValue;
  if (ArgValue.starts_with("*+")) {
    StringValue = ArgValue.substr(2);
  } else if (ArgValue.starts_with("*-")) {
    StringValue = ArgValue.substr(1);
  } else if (ArgValue.contains("=")) {
    return createStringError(errc::invalid_argument,
                             "bad format for " + OptionName +
                                 ": changing LMA to a specific value is not "
                                 "supported. Use *+val or *-val instead");
  } else if (ArgValue.contains("+") || ArgValue.contains("-")) {
    return createStringError(errc::invalid_argument,
                             "bad format for " + OptionName +
                                 ": changing a specific section LMA is not "
                                 "supported. Use *+val or *-val instead");
  }
  if (StringValue.empty())
    return createStringError(errc::invalid_argument,
                             "bad format for " + OptionName +
                                 ": missing LMA offset");

  auto LMAValue = getAsInteger<int64_t>(StringValue);
  if (!LMAValue)
    return createStringError(LMAValue.getError(),
                             "bad format for " + OptionName + ": value after " +
                                 ArgValue.slice(0, 2) + " is " + StringValue +
                                 " when it should be an integer");
  return *LMAValue;
}

static Expected<SectionPatternAddressUpdate>
parseChangeSectionAddr(StringRef ArgValue, StringRef OptionName,
                       MatchStyle SectionMatchStyle,
                       function_ref<Error(Error)> ErrorCallback) {
  SectionPatternAddressUpdate PatternUpdate;

  size_t LastSymbolIndex = ArgValue.find_last_of("+-=");
  if (LastSymbolIndex == StringRef::npos)
    return createStringError(errc::invalid_argument,
                             "bad format for " + OptionName +
                                 ": argument value " + ArgValue +
                                 " is invalid. See --help");
  char UpdateSymbol = ArgValue[LastSymbolIndex];

  StringRef SectionPattern = ArgValue.slice(0, LastSymbolIndex);
  if (SectionPattern.empty())
    return createStringError(
        errc::invalid_argument,
        "bad format for " + OptionName +
            ": missing section pattern to apply address change to");
  if (Error E = PatternUpdate.SectionPattern.addMatcher(NameOrPattern::create(
          SectionPattern, SectionMatchStyle, ErrorCallback)))
    return std::move(E);

  StringRef Value = ArgValue.substr(LastSymbolIndex + 1);
  if (Value.empty()) {
    switch (UpdateSymbol) {
    case '+':
    case '-':
      return createStringError(errc::invalid_argument,
                               "bad format for " + OptionName +
                                   ": missing value of offset after '" +
                                   std::string({UpdateSymbol}) + "'");

    case '=':
      return createStringError(errc::invalid_argument,
                               "bad format for " + OptionName +
                                   ": missing address value after '='");
    }
  }
  auto AddrValue = getAsInteger<uint64_t>(Value);
  if (!AddrValue)
    return createStringError(AddrValue.getError(),
                             "bad format for " + OptionName + ": value after " +
                                 std::string({UpdateSymbol}) + " is " + Value +
                                 " when it should be a 64-bit integer");

  switch (UpdateSymbol) {
  case '+':
    PatternUpdate.Update.Kind = AdjustKind::Add;
    break;
  case '-':
    PatternUpdate.Update.Kind = AdjustKind::Subtract;
    break;
  case '=':
    PatternUpdate.Update.Kind = AdjustKind::Set;
  }

  PatternUpdate.Update.Value = *AddrValue;
  return PatternUpdate;
}

// parseObjcopyOptions returns the config and sets the input arguments. If a
// help flag is set then parseObjcopyOptions will print the help messege and
// exit.
Expected<DriverConfig>
objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
                             function_ref<Error(Error)> ErrorCallback) {
  DriverConfig DC;
  ObjcopyOptTable T;

  unsigned MissingArgumentIndex, MissingArgumentCount;
  llvm::opt::InputArgList InputArgs =
      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);

  if (MissingArgumentCount)
    return createStringError(
        errc::invalid_argument,
        "argument to '%s' is missing (expected %d value(s))",
        InputArgs.getArgString(MissingArgumentIndex), MissingArgumentCount);

  if (InputArgs.size() == 0) {
    printHelp(T, errs(), ToolType::Objcopy);
    exit(1);
  }

  if (InputArgs.hasArg(OBJCOPY_help)) {
    printHelp(T, outs(), ToolType::Objcopy);
    exit(0);
  }

  if (InputArgs.hasArg(OBJCOPY_version)) {
    outs() << "llvm-objcopy, compatible with GNU objcopy\n";
    cl::PrintVersionMessage();
    exit(0);
  }

  SmallVector<const char *, 2> Positional;

  for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
    return createStringError(errc::invalid_argument, "unknown argument '%s'",
                             Arg->getAsString(InputArgs).c_str());

  for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
    Positional.push_back(Arg->getValue());

  if (Positional.empty())
    return createStringError(errc::invalid_argument, "no input file specified");

  if (Positional.size() > 2)
    return createStringError(errc::invalid_argument,
                             "too many positional arguments");

  ConfigManager ConfigMgr;
  CommonConfig &Config = ConfigMgr.Common;
  COFFConfig &COFFConfig = ConfigMgr.COFF;
  ELFConfig &ELFConfig = ConfigMgr.ELF;
  MachOConfig &MachOConfig = ConfigMgr.MachO;
  Config.InputFilename = Positional[0];
  Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
  if (InputArgs.hasArg(OBJCOPY_target) &&
      (InputArgs.hasArg(OBJCOPY_input_target) ||
       InputArgs.hasArg(OBJCOPY_output_target)))
    return createStringError(
        errc::invalid_argument,
        "--target cannot be used with --input-target or --output-target");

  if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
    return createStringError(errc::invalid_argument,
                             "--regex and --wildcard are incompatible");

  MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
                                     ? MatchStyle::Regex
                                     : MatchStyle::Wildcard;
  MatchStyle SymbolMatchStyle
      = InputArgs.hasArg(OBJCOPY_regex)    ? MatchStyle::Regex
      : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard
                                           : MatchStyle::Literal;
  StringRef InputFormat, OutputFormat;
  if (InputArgs.hasArg(OBJCOPY_target)) {
    InputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
    OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
  } else {
    InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
    OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
  }

  // FIXME:  Currently, we ignore the target for non-binary/ihex formats
  // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the
  // format by llvm::object::createBinary regardless of the option value.
  Config.InputFormat = StringSwitch<FileFormat>(InputFormat)
                           .Case("binary", FileFormat::Binary)
                           .Case("ihex", FileFormat::IHex)
                           .Default(FileFormat::Unspecified);

  if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) {
    const uint8_t Invalid = 0xff;
    StringRef VisibilityStr =
        InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);

    ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr)
                                        .Case("default", ELF::STV_DEFAULT)
                                        .Case("hidden", ELF::STV_HIDDEN)
                                        .Case("internal", ELF::STV_INTERNAL)
                                        .Case("protected", ELF::STV_PROTECTED)
                                        .Default(Invalid);

    if (ELFConfig.NewSymbolVisibility == Invalid)
      return createStringError(errc::invalid_argument,
                               "'%s' is not a valid symbol visibility",
                               VisibilityStr.str().c_str());
  }

  for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) {
    StringRef Subsystem, Version;
    std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':');
    COFFConfig.Subsystem =
        StringSwitch<unsigned>(Subsystem.lower())
            .Case("boot_application",
                  COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
            .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
            .Cases({"efi_application", "efi-app"},
                   COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION)
            .Cases({"efi_boot_service_driver", "efi-bsd"},
                   COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
            .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM)
            .Cases({"efi_runtime_driver", "efi-rtd"},
                   COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
            .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE)
            .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI)
            .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
            .Case("xbox", COFF::IMAGE_SUBSYSTEM_XBOX)
            .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN);
    if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN)
      return createStringError(errc::invalid_argument,
                               "'%s' is not a valid subsystem",
                               Subsystem.str().c_str());
    if (!Version.empty()) {
      StringRef Major, Minor;
      std::tie(Major, Minor) = Version.split('.');
      unsigned Number;
      if (Major.getAsInteger(10, Number))
        return createStringError(errc::invalid_argument,
                                 "'%s' is not a valid subsystem major version",
                                 Major.str().c_str());
      COFFConfig.MajorSubsystemVersion = Number;
      Number = 0;
      if (!Minor.empty() && Minor.getAsInteger(10, Number))
        return createStringError(errc::invalid_argument,
                                 "'%s' is not a valid subsystem minor version",
                                 Minor.str().c_str());
      COFFConfig.MinorSubsystemVersion = Number;
    }
  }

  Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
                            .Case("binary", FileFormat::Binary)
                            .Case("ihex", FileFormat::IHex)
                            .Case("srec", FileFormat::SREC)
                            .Default(FileFormat::Unspecified);
  if (Config.OutputFormat == FileFormat::Unspecified) {
    if (OutputFormat.empty()) {
      Config.OutputFormat = Config.InputFormat;
    } else {
      Expected<TargetInfo> Target =
          getOutputTargetInfoByTargetName(OutputFormat);
      if (!Target)
        return Target.takeError();
      Config.OutputFormat = Target->Format;
      Config.OutputArch = Target->Machine;
    }
  }

  if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) {
    Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue())
                                 .Case("zlib", DebugCompressionType::Zlib)
                                 .Case("zstd", DebugCompressionType::Zstd)
                                 .Default(DebugCompressionType::None);
    if (Config.CompressionType == DebugCompressionType::None) {
      return createStringError(
          errc::invalid_argument,
          "invalid or unsupported --compress-debug-sections format: %s",
          A->getValue());
    }
    if (const char *Reason = compression::getReasonIfUnsupported(
            compression::formatFor(Config.CompressionType)))
      return createStringError(errc::invalid_argument, Reason);
  }

  for (const auto *A : InputArgs.filtered(OBJCOPY_compress_sections)) {
    SmallVector<StringRef, 0> Fields;
    StringRef(A->getValue()).split(Fields, '=');
    if (Fields.size() != 2 || Fields[1].empty()) {
      return createStringError(
          errc::invalid_argument,
          A->getSpelling() +
              ": parse error, not 'section-glob=[none|zlib|zstd]'");
    }

    auto Type = StringSwitch<DebugCompressionType>(Fields[1])
                    .Case("zlib", DebugCompressionType::Zlib)
                    .Case("zstd", DebugCompressionType::Zstd)
                    .Default(DebugCompressionType::None);
    if (Type == DebugCompressionType::None && Fields[1] != "none") {
      return createStringError(
          errc::invalid_argument,
          "invalid or unsupported --compress-sections format: %s",
          A->getValue());
    }
    if (Type != DebugCompressionType::None) {
      if (const char *Reason =
              compression::getReasonIfUnsupported(compression::formatFor(Type)))
        return createStringError(errc::invalid_argument, Reason);
    }

    auto &P = Config.compressSections.emplace_back();
    P.second = Type;
    auto Matcher =
        NameOrPattern::create(Fields[0], SectionMatchStyle, ErrorCallback);
    // =none allows overriding a previous =zlib or =zstd. Reject negative
    // patterns, which would be confusing.
    if (Matcher && !Matcher->isPositiveMatch()) {
      return createStringError(
          errc::invalid_argument,
          "--compress-sections: negative pattern is unsupported");
    }
    if (Error E = P.first.addMatcher(std::move(Matcher)))
      return std::move(E);
  }

  Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
  // The gnu_debuglink's target is expected to not change or else its CRC would
  // become invalidated and get rejected. We can avoid recalculating the
  // checksum for every target file inside an archive by precomputing the CRC
  // here. This prevents a significant amount of I/O.
  if (!Config.AddGnuDebugLink.empty()) {
    auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink);
    if (!DebugOrErr)
      return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());
    auto Debug = std::move(*DebugOrErr);
    Config.GnuDebugLinkCRC32 =
        llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
  }
  Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);

  Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
  Config.SymbolsPrefixRemove =
      InputArgs.getLastArgValue(OBJCOPY_remove_symbol_prefix);

  Config.AllocSectionsPrefix =
      InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
  if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
    Config.ExtractPartition = Arg->getValue();

  if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) {
    if (Config.OutputFormat != FileFormat::Binary)
      return createStringError(
          errc::invalid_argument,
          "'--gap-fill' is only supported for binary output");
    ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue());
    if (!Val)
      return createStringError(Val.getError(), "--gap-fill: bad number: %s",
                               A->getValue());
    uint8_t ByteVal = Val.get();
    if (ByteVal != Val.get())
      return createStringError(std::errc::value_too_large,
                               "gap-fill value %s is out of range (0 to 0xff)",
                               A->getValue());
    Config.GapFill = ByteVal;
  }

  if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) {
    if (Config.OutputFormat != FileFormat::Binary)
      return createStringError(
          errc::invalid_argument,
          "'--pad-to' is only supported for binary output");
    ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue());
    if (!Addr)
      return createStringError(Addr.getError(), "--pad-to: bad number: %s",
                               A->getValue());
    Config.PadTo = *Addr;
  }

  if (const auto *Arg = InputArgs.getLastArg(OBJCOPY_change_section_lma)) {
    Expected<int64_t> LMAValue =
        parseChangeSectionLMA(Arg->getValue(), Arg->getSpelling());
    if (!LMAValue)
      return LMAValue.takeError();
    Config.ChangeSectionLMAValAll = *LMAValue;
  }

  for (auto *Arg : InputArgs.filtered(OBJCOPY_change_section_address)) {
    Expected<SectionPatternAddressUpdate> AddressUpdate =
        parseChangeSectionAddr(Arg->getValue(), Arg->getSpelling(),
                               SectionMatchStyle, ErrorCallback);
    if (!AddressUpdate)
      return AddressUpdate.takeError();
    Config.ChangeSectionAddress.push_back(*AddressUpdate);
  }

  for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
    if (!StringRef(Arg->getValue()).contains('='))
      return createStringError(errc::invalid_argument,
                               "bad format for --redefine-sym");
    auto Old2New = StringRef(Arg->getValue()).split('=');
    if (!Config.SymbolsToRename.insert(Old2New).second)
      return createStringError(errc::invalid_argument,
                               "multiple redefinition of symbol '%s'",
                               Old2New.first.str().c_str());
  }

  for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
    if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
                                             Arg->getValue()))
      return std::move(E);

  for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
    Expected<SectionRename> SR =
        parseRenameSectionValue(StringRef(Arg->getValue()));
    if (!SR)
      return SR.takeError();
    if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
      return createStringError(errc::invalid_argument,
                               "multiple renames of section '%s'",
                               SR->OriginalName.str().c_str());
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
    Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
        parseSetSectionAttribute("--set-section-alignment", Arg->getValue());
    if (!NameAndAlign)
      return NameAndAlign.takeError();
    Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
    Expected<SectionFlagsUpdate> SFU =
        parseSetSectionFlagValue(Arg->getValue());
    if (!SFU)
      return SFU.takeError();
    if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
      return createStringError(
          errc::invalid_argument,
          "--set-section-flags set multiple times for section '%s'",
          SFU->Name.str().c_str());
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) {
    Expected<std::pair<StringRef, uint64_t>> NameAndType =
        parseSetSectionAttribute("--set-section-type", Arg->getValue());
    if (!NameAndType)
      return NameAndType.takeError();
    Config.SetSectionType[NameAndType->first] = NameAndType->second;
  }
  // Prohibit combinations of --set-section-{flags,type} when the section name
  // is used as the destination of a --rename-section.
  for (const auto &E : Config.SectionsToRename) {
    const SectionRename &SR = E.second;
    auto Err = [&](const char *Option) {
      return createStringError(
          errc::invalid_argument,
          "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option,
          SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
          SR.NewName.str().c_str());
    };
    if (Config.SetSectionFlags.count(SR.NewName))
      return Err("flags");
    if (Config.SetSectionType.count(SR.NewName))
      return Err("type");
  }

  for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section))
    if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section))
    if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section))
    if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) {
    if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section",
                                       Config.AddSection))
      return std::move(Err);
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) {
    if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section",
                                       Config.UpdateSection))
      return std::move(Err);
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
    StringRef Value(Arg->getValue());
    if (Value.split('=').second.empty())
      return createStringError(
          errc::invalid_argument,
          "bad format for --dump-section, expected section=file");
    Config.DumpSection.push_back(Value);
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_extract_section)) {
    StringRef Value(Arg->getValue());
    if (Value.split('=').second.empty())
      return createStringError(
          errc::invalid_argument,
          "bad format for --extract-section, expected section=file");
    Config.ExtractSection.push_back(Value);
  }
  Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
  Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
  Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
  Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
  Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
  Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
  Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
  Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
  Config.ExtractMainPartition =
      InputArgs.hasArg(OBJCOPY_extract_main_partition);
  ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
  Config.Verbose = InputArgs.hasArg(OBJCOPY_verbose);
  Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
  if (auto *Arg =
          InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
    Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all)
                             ? DiscardType::All
                             : DiscardType::Locals;
  }

  ELFConfig.VerifyNoteSections = InputArgs.hasFlag(
      OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true);

  Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
  ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
  MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
  Config.DecompressDebugSections =
      InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
  if (Config.DiscardMode == DiscardType::All) {
    Config.StripDebug = true;
    ELFConfig.KeepFileSymbols = true;
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
    if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
    if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
                                     Arg->getValue(), SymbolMatchStyle,
                                     ErrorCallback))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
    if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
    if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
                                     Arg->getValue(), SymbolMatchStyle,
                                     ErrorCallback))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
    if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
    if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
                                     Arg->getValue(), SymbolMatchStyle,
                                     ErrorCallback))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
    if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
    if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
                                     Arg->getValue(), SymbolMatchStyle,
                                     ErrorCallback))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
    if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
    if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
                                     Arg->getValue(), SymbolMatchStyle,
                                     ErrorCallback))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
    if (Error E =
            Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
                Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
    if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
                                     Arg->getValue(), SymbolMatchStyle,
                                     ErrorCallback))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
    if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
    if (Error E =
            addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
                               SymbolMatchStyle, ErrorCallback))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol))
    if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols))
    if (Error E =
            addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(),
                               SymbolMatchStyle, ErrorCallback))
      return std::move(E);
  for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
    Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
    if (!SymInfo)
      return SymInfo.takeError();

    Config.SymbolsToAdd.push_back(*SymInfo);
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbol_visibility)) {
    if (!StringRef(Arg->getValue()).contains('='))
      return createStringError(errc::invalid_argument,
                               "bad format for --set-symbol-visibility");
    auto [Sym, Visibility] = StringRef(Arg->getValue()).split('=');
    Expected<uint8_t> Type = parseVisibilityType(Visibility);
    if (!Type)
      return Type.takeError();
    ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type);
    if (Error E = ELFConfig.SymbolsToSetVisibility.back().first.addMatcher(
            NameOrPattern::create(Sym, SymbolMatchStyle, ErrorCallback)))
      return std::move(E);
  }
  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbols_visibility)) {
    if (!StringRef(Arg->getValue()).contains('='))
      return createStringError(errc::invalid_argument,
                               "bad format for --set-symbols-visibility");
    auto [File, Visibility] = StringRef(Arg->getValue()).split('=');
    Expected<uint8_t> Type = parseVisibilityType(Visibility);
    if (!Type)
      return Type.takeError();
    ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type);
    if (Error E =
            addSymbolsFromFile(ELFConfig.SymbolsToSetVisibility.back().first,
                               DC.Alloc, File, SymbolMatchStyle, ErrorCallback))
      return std::move(E);
  }

  ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);

  Config.DeterministicArchives = InputArgs.hasFlag(
      OBJCOPY_enable_deterministic_archives,
      OBJCOPY_disable_deterministic_archives, /*default=*/true);

  Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);

  if (Config.PreserveDates &&
      (Config.OutputFilename == "-" || Config.InputFilename == "-"))
    return createStringError(errc::invalid_argument,
                             "--preserve-dates requires a file");

  for (auto *Arg : InputArgs)
    if (Arg->getOption().matches(OBJCOPY_set_start)) {
      auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
      if (!EAddr)
        return createStringError(
            EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());

      ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
    } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
      auto EIncr = getAsInteger<int64_t>(Arg->getValue());
      if (!EIncr)
        return createStringError(EIncr.getError(),
                                 "bad entry point increment: '%s'",
                                 Arg->getValue());
      auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr)
                                      : [](uint64_t A) { return A; };
      ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
        return Expr(EAddr) + *EIncr;
      };
    }

  for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_note)) {
    Expected<RemoveNoteInfo> NoteInfo = parseRemoveNoteInfo(Arg->getValue());
    if (!NoteInfo)
      return NoteInfo.takeError();

    ELFConfig.NotesToRemove.push_back(*NoteInfo);
  }

  if (!ELFConfig.NotesToRemove.empty()) {
    if (!Config.ToRemove.empty())
      return createStringError(
          errc::invalid_argument,
          "cannot specify both --remove-note and --remove-section");
    if (!Config.AddSection.empty())
      return createStringError(
          errc::invalid_argument,
          "cannot specify both --remove-note and --add-section");
    if (!Config.UpdateSection.empty())
      return createStringError(
          errc::invalid_argument,
          "cannot specify both --remove-note and --update-section");
  }

  if (Config.DecompressDebugSections &&
      Config.CompressionType != DebugCompressionType::None) {
    return createStringError(
        errc::invalid_argument,
        "cannot specify both --compress-debug-sections and "
        "--decompress-debug-sections");
  }

  if (Config.ExtractPartition && Config.ExtractMainPartition)
    return createStringError(errc::invalid_argument,
                             "cannot specify --extract-partition together with "
                             "--extract-main-partition");

  DC.CopyConfigs.push_back(std::move(ConfigMgr));
  return std::move(DC);
}

// parseInstallNameToolOptions returns the config and sets the input arguments.
// If a help flag is set then parseInstallNameToolOptions will print the help
// messege and exit.
Expected<DriverConfig>
objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
  DriverConfig DC;
  ConfigManager ConfigMgr;
  CommonConfig &Config = ConfigMgr.Common;
  MachOConfig &MachOConfig = ConfigMgr.MachO;
  InstallNameToolOptTable T;
  unsigned MissingArgumentIndex, MissingArgumentCount;
  llvm::opt::InputArgList InputArgs =
      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);

  if (MissingArgumentCount)
    return createStringError(
        errc::invalid_argument,
        "missing argument to " +
            StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
            " option");

  if (InputArgs.size() == 0) {
    printHelp(T, errs(), ToolType::InstallNameTool);
    exit(1);
  }

  if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
    printHelp(T, outs(), ToolType::InstallNameTool);
    exit(0);
  }

  if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
    outs() << "llvm-install-name-tool, compatible with cctools "
              "install_name_tool\n";
    cl::PrintVersionMessage();
    exit(0);
  }

  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
    MachOConfig.RPathToAdd.push_back(Arg->getValue());

  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
    MachOConfig.RPathToPrepend.push_back(Arg->getValue());

  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
    StringRef RPath = Arg->getValue();

    // Cannot add and delete the same rpath at the same time.
    if (is_contained(MachOConfig.RPathToAdd, RPath))
      return createStringError(
          errc::invalid_argument,
          "cannot specify both -add_rpath '%s' and -delete_rpath '%s'",
          RPath.str().c_str(), RPath.str().c_str());
    if (is_contained(MachOConfig.RPathToPrepend, RPath))
      return createStringError(
          errc::invalid_argument,
          "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'",
          RPath.str().c_str(), RPath.str().c_str());

    MachOConfig.RPathsToRemove.insert(RPath);
  }

  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) {
    StringRef Old = Arg->getValue(0);
    StringRef New = Arg->getValue(1);

    auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; };

    // Cannot specify duplicate -rpath entries
    auto It1 = find_if(
        MachOConfig.RPathsToUpdate,
        [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) {
          return Match(OldNew.getFirst()) || Match(OldNew.getSecond());
        });
    if (It1 != MachOConfig.RPathsToUpdate.end())
      return createStringError(errc::invalid_argument,
                               "cannot specify both -rpath '" +
                                   It1->getFirst() + "' '" + It1->getSecond() +
                                   "' and -rpath '" + Old + "' '" + New + "'");

    // Cannot specify the same rpath under both -delete_rpath and -rpath
    auto It2 = find_if(MachOConfig.RPathsToRemove, Match);
    if (It2 != MachOConfig.RPathsToRemove.end())
      return createStringError(errc::invalid_argument,
                               "cannot specify both -delete_rpath '" + *It2 +
                                   "' and -rpath '" + Old + "' '" + New + "'");

    // Cannot specify the same rpath under both -add_rpath and -rpath
    auto It3 = find_if(MachOConfig.RPathToAdd, Match);
    if (It3 != MachOConfig.RPathToAdd.end())
      return createStringError(errc::invalid_argument,
                               "cannot specify both -add_rpath '" + *It3 +
                                   "' and -rpath '" + Old + "' '" + New + "'");

    // Cannot specify the same rpath under both -prepend_rpath and -rpath.
    auto It4 = find_if(MachOConfig.RPathToPrepend, Match);
    if (It4 != MachOConfig.RPathToPrepend.end())
      return createStringError(errc::invalid_argument,
                               "cannot specify both -prepend_rpath '" + *It4 +
                                   "' and -rpath '" + Old + "' '" + New + "'");

    MachOConfig.RPathsToUpdate.insert({Old, New});
  }

  if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) {
    MachOConfig.SharedLibId = Arg->getValue();
    if (MachOConfig.SharedLibId->empty())
      return createStringError(errc::invalid_argument,
                               "cannot specify an empty id");
  }

  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change))
    MachOConfig.InstallNamesToUpdate.insert(
        {Arg->getValue(0), Arg->getValue(1)});

  MachOConfig.RemoveAllRpaths =
      InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);

  SmallVector<StringRef, 2> Positional;
  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
    return createStringError(errc::invalid_argument, "unknown argument '%s'",
                             Arg->getAsString(InputArgs).c_str());
  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
    Positional.push_back(Arg->getValue());
  if (Positional.empty())
    return createStringError(errc::invalid_argument, "no input file specified");
  if (Positional.size() > 1)
    return createStringError(
        errc::invalid_argument,
        "llvm-install-name-tool expects a single input file");
  Config.InputFilename = Positional[0];
  Config.OutputFilename =
      InputArgs.getLastArgValue(INSTALL_NAME_TOOL_output, Positional[0]);

  Expected<OwningBinary<Binary>> BinaryOrErr =
      createBinary(Config.InputFilename);
  if (!BinaryOrErr)
    return createFileError(Config.InputFilename, BinaryOrErr.takeError());
  auto *Binary = (*BinaryOrErr).getBinary();
  if (!Binary->isMachO() && !Binary->isMachOUniversalBinary())
    return createStringError(errc::invalid_argument,
                             "input file: %s is not a Mach-O file",
                             Config.InputFilename.str().c_str());

  DC.CopyConfigs.push_back(std::move(ConfigMgr));
  return std::move(DC);
}

Expected<DriverConfig>
objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
                                  function_ref<Error(Error)> ErrorCallback) {
  DriverConfig DC;
  ConfigManager ConfigMgr;
  CommonConfig &Config = ConfigMgr.Common;
  MachOConfig &MachOConfig = ConfigMgr.MachO;
  BitcodeStripOptTable T;
  unsigned MissingArgumentIndex, MissingArgumentCount;
  opt::InputArgList InputArgs =
      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);

  if (InputArgs.size() == 0) {
    printHelp(T, errs(), ToolType::BitcodeStrip);
    exit(1);
  }

  if (InputArgs.hasArg(BITCODE_STRIP_help)) {
    printHelp(T, outs(), ToolType::BitcodeStrip);
    exit(0);
  }

  if (InputArgs.hasArg(BITCODE_STRIP_version)) {
    outs() << "llvm-bitcode-strip, compatible with cctools "
              "bitcode_strip\n";
    cl::PrintVersionMessage();
    exit(0);
  }

  for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN))
    return createStringError(errc::invalid_argument, "unknown argument '%s'",
                             Arg->getAsString(InputArgs).c_str());

  SmallVector<StringRef, 2> Positional;
  for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
    Positional.push_back(Arg->getValue());
  if (Positional.size() > 1)
    return createStringError(errc::invalid_argument,
                             "llvm-bitcode-strip expects a single input file");
  assert(!Positional.empty());
  Config.InputFilename = Positional[0];

  if (!InputArgs.hasArg(BITCODE_STRIP_output)) {
    return createStringError(errc::invalid_argument,
                             "-o is a required argument");
  }
  Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output);

  if (!InputArgs.hasArg(BITCODE_STRIP_remove))
    return createStringError(errc::invalid_argument, "no action specified");

  // We only support -r for now, which removes all bitcode sections and
  // the __LLVM segment if it's now empty.
  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
      "__LLVM,__asm", MatchStyle::Literal, ErrorCallback)));
  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
      "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback)));
  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
      "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback)));
  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
      "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback)));
  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
      "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback)));
  MachOConfig.EmptySegmentsToRemove.insert("__LLVM");

  DC.CopyConfigs.push_back(std::move(ConfigMgr));
  return std::move(DC);
}

// parseStripOptions returns the config and sets the input arguments. If a
// help flag is set then parseStripOptions will print the help messege and
// exit.
Expected<DriverConfig>
objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
                           function_ref<Error(Error)> ErrorCallback) {
  const char *const *DashDash =
      llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
  ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
  if (DashDash != RawArgsArr.end())
    DashDash = std::next(DashDash);

  StripOptTable T;
  unsigned MissingArgumentIndex, MissingArgumentCount;
  llvm::opt::InputArgList InputArgs =
      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);

  if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
    printHelp(T, errs(), ToolType::Strip);
    exit(1);
  }

  if (InputArgs.hasArg(STRIP_help)) {
    printHelp(T, outs(), ToolType::Strip);
    exit(0);
  }

  if (InputArgs.hasArg(STRIP_version)) {
    outs() << "llvm-strip, compatible with GNU strip\n";
    cl::PrintVersionMessage();
    exit(0);
  }

  SmallVector<StringRef, 2> Positional;
  for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
    return createStringError(errc::invalid_argument, "unknown argument '%s'",
                             Arg->getAsString(InputArgs).c_str());
  for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
    Positional.push_back(Arg->getValue());
  std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));

  if (Positional.empty())
    return createStringError(errc::invalid_argument, "no input file specified");

  if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
    return createStringError(
        errc::invalid_argument,
        "multiple input files cannot be used in combination with -o");

  ConfigManager ConfigMgr;
  CommonConfig &Config = ConfigMgr.Common;
  ELFConfig &ELFConfig = ConfigMgr.ELF;
  MachOConfig &MachOConfig = ConfigMgr.MachO;

  if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
    return createStringError(errc::invalid_argument,
                             "--regex and --wildcard are incompatible");
  MatchStyle SectionMatchStyle =
      InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
  MatchStyle SymbolMatchStyle
      = InputArgs.hasArg(STRIP_regex)    ? MatchStyle::Regex
      : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard
                                         : MatchStyle::Literal;
  ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
  Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);

  if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals))
    Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all)
                             ? DiscardType::All
                             : DiscardType::Locals;
  Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
  Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
  if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
    Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
  Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
  MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
  Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
  ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
  MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);

  for (auto *Arg : InputArgs.filtered(STRIP_keep_section))
    if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
      return std::move(E);

  for (auto *Arg : InputArgs.filtered(STRIP_remove_section))
    if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
            Arg->getValue(), SectionMatchStyle, ErrorCallback)))
      return std::move(E);

  for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol))
    if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);

  for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol))
    if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
            Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
      return std::move(E);

  if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
      !Config.OnlyKeepDebug && !Config.StripUnneeded &&
      Config.DiscardMode == DiscardType::None && !Config.StripAllGNU &&
      Config.SymbolsToRemove.empty())
    Config.StripAll = true;

  if (Config.DiscardMode == DiscardType::All) {
    Config.StripDebug = true;
    ELFConfig.KeepFileSymbols = true;
  }

  Config.DeterministicArchives =
      InputArgs.hasFlag(STRIP_enable_deterministic_archives,
                        STRIP_disable_deterministic_archives, /*default=*/true);

  Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
  Config.Verbose = InputArgs.hasArg(STRIP_verbose);
  Config.InputFormat = FileFormat::Unspecified;
  Config.OutputFormat = FileFormat::Unspecified;

  DriverConfig DC;
  if (Positional.size() == 1) {
    Config.InputFilename = Positional[0];
    Config.OutputFilename =
        InputArgs.getLastArgValue(STRIP_output, Positional[0]);
    DC.CopyConfigs.push_back(std::move(ConfigMgr));
  } else {
    StringMap<unsigned> InputFiles;
    for (StringRef Filename : Positional) {
      if (InputFiles[Filename]++ == 1) {
        if (Filename == "-")
          return createStringError(
              errc::invalid_argument,
              "cannot specify '-' as an input file more than once");
        if (Error E = ErrorCallback(createStringError(
                errc::invalid_argument, "'%s' was already specified",
                Filename.str().c_str())))
          return std::move(E);
      }
      Config.InputFilename = Filename;
      Config.OutputFilename = Filename;
      DC.CopyConfigs.push_back(ConfigMgr);
    }
  }

  if (Config.PreserveDates && (is_contained(Positional, "-") ||
                               InputArgs.getLastArgValue(STRIP_output) == "-"))
    return createStringError(errc::invalid_argument,
                             "--preserve-dates requires a file");

  return std::move(DC);
}

Error llvm::objcopy::runExtractBundleEntry(
    const SmallVectorImpl<StringRef> &Args) {
  for (StringRef Input : Args)
    if (Error Err = object::extractOffloadBundleByURI(Input))
      return Err;

  return Error::success();
}

Expected<SmallVector<StringRef>>
objcopy::parseExtractBundleEntryOptions(ArrayRef<const char *> ArgsArr) {
  ExtractBundleEntryOptTable T;
  unsigned MissingArgumentIndex, MissingArgumentCount;
  opt::InputArgList InputArgs =
      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);

  if (InputArgs.size() == 0) {
    printHelp(T, errs(), ToolType::ExtractBundleEntry);
    exit(1);
  }

  if (InputArgs.hasArg(EXTRACT_BUNDLE_ENTRY_help)) {
    printHelp(T, outs(), ToolType::ExtractBundleEntry);
    exit(0);
  }

  if (InputArgs.hasArg(EXTRACT_BUNDLE_ENTRY_version)) {
    outs() << "llvm-extract-bundle-entry\n";
    cl::PrintVersionMessage();
    exit(0);
  }

  for (auto *Arg : InputArgs.filtered(EXTRACT_BUNDLE_ENTRY_UNKNOWN))
    return createStringError(errc::invalid_argument, "unknown argument '%s'",
                             Arg->getAsString(InputArgs).c_str());

  SmallVector<StringRef> Arguments;

  for (auto *Arg : InputArgs.filtered(EXTRACT_BUNDLE_ENTRY_INPUT))
    Arguments.push_back(Arg->getValue());
  assert(!Arguments.empty());

  return Arguments;
}
