diff options
Diffstat (limited to 'contrib/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp | 459 | 
1 files changed, 285 insertions, 174 deletions
diff --git a/contrib/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp b/contrib/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp index 8d6431b3044f..73ed00b5cb2a 100644 --- a/contrib/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp +++ b/contrib/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp @@ -14,10 +14,10 @@  #include "llvm/ADT/StringSet.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/JamCRC.h"  #include "llvm/Support/MemoryBuffer.h"  #include "llvm/Support/StringSaver.h"  #include <memory> @@ -63,6 +63,44 @@ public:    ObjcopyOptTable() : OptTable(ObjcopyInfoTable) {}  }; +enum InstallNameToolID { +  INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID. +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \ +               HELPTEXT, METAVAR, VALUES)                                      \ +  INSTALL_NAME_TOOL_##ID, +#include "InstallNameToolOpts.inc" +#undef OPTION +}; + +#define PREFIX(NAME, VALUE)                                                    \ +  const char *const INSTALL_NAME_TOOL_##NAME[] = VALUE; +#include "InstallNameToolOpts.inc" +#undef PREFIX + +static const opt::OptTable::Info InstallNameToolInfoTable[] = { +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \ +               HELPTEXT, METAVAR, VALUES)                                      \ +  {INSTALL_NAME_TOOL_##PREFIX,                                                 \ +   NAME,                                                                       \ +   HELPTEXT,                                                                   \ +   METAVAR,                                                                    \ +   INSTALL_NAME_TOOL_##ID,                                                     \ +   opt::Option::KIND##Class,                                                   \ +   PARAM,                                                                      \ +   FLAGS,                                                                      \ +   INSTALL_NAME_TOOL_##GROUP,                                                  \ +   INSTALL_NAME_TOOL_##ALIAS,                                                  \ +   ALIASARGS,                                                                  \ +   VALUES}, +#include "InstallNameToolOpts.inc" +#undef OPTION +}; + +class InstallNameToolOptTable : public opt::OptTable { +public: +  InstallNameToolOptTable() : OptTable(InstallNameToolInfoTable) {} +}; +  enum StripID {    STRIP_INVALID = 0, // This is not an option ID.  #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \ @@ -155,6 +193,25 @@ static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {    return SR;  } +static Expected<std::pair<StringRef, uint64_t>> +parseSetSectionAlignment(StringRef FlagValue) { +  if (!FlagValue.contains('=')) +    return createStringError( +        errc::invalid_argument, +        "bad format for --set-section-alignment: missing '='"); +  auto Split = StringRef(FlagValue).split('='); +  if (Split.first.empty()) +    return createStringError( +        errc::invalid_argument, +        "bad format for --set-section-alignment: missing section name"); +  uint64_t NewAlign; +  if (Split.second.getAsInteger(0, NewAlign)) +    return createStringError(errc::invalid_argument, +                             "invalid alignment for --set-section-alignment: '%s'", +                             Split.second.str().c_str()); +  return std::make_pair(Split.first, NewAlign); +} +  static Expected<SectionFlagsUpdate>  parseSetSectionFlagValue(StringRef FlagValue) {    if (!StringRef(FlagValue).contains('=')) @@ -177,106 +234,6 @@ parseSetSectionFlagValue(StringRef FlagValue) {    return SFU;  } -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: -  //           The following are currently supported: -  // -  //           global, local, weak, default, hidden, file, section, object, -  //           indirect-function. -  // -  //           The following flags are ignored and provided for GNU -  //           compatibility only: -  // -  //           warning, debug, constructor, indirect, synthetic, -  //           unique-object, before=<symbol>. -  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(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] { SI.Bind = ELF::STB_GLOBAL; }) -            .CaseLower("local", [&SI] { SI.Bind = ELF::STB_LOCAL; }) -            .CaseLower("weak", [&SI] { SI.Bind = ELF::STB_WEAK; }) -            .CaseLower("default", [&SI] { SI.Visibility = ELF::STV_DEFAULT; }) -            .CaseLower("hidden", [&SI] { SI.Visibility = ELF::STV_HIDDEN; }) -            .CaseLower("file", [&SI] { SI.Type = ELF::STT_FILE; }) -            .CaseLower("section", [&SI] { SI.Type = ELF::STT_SECTION; }) -            .CaseLower("object", [&SI] { SI.Type = ELF::STT_OBJECT; }) -            .CaseLower("function", [&SI] { SI.Type = ELF::STT_FUNC; }) -            .CaseLower("indirect-function", -                       [&SI] { SI.Type = ELF::STT_GNU_IFUNC; }) -            .CaseLower("debug", [] {}) -            .CaseLower("constructor", [] {}) -            .CaseLower("warning", [] {}) -            .CaseLower("indirect", [] {}) -            .CaseLower("synthetic", [] {}) -            .CaseLower("unique-object", [] {}) -            .StartsWithLower("before", [] {}) -            .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 const StringMap<MachineInfo> ArchMap{ -    // Name, {EMachine, 64bit, LittleEndian} -    {"aarch64", {ELF::EM_AARCH64, true, true}}, -    {"arm", {ELF::EM_ARM, false, true}}, -    {"i386", {ELF::EM_386, false, true}}, -    {"i386:x86-64", {ELF::EM_X86_64, true, true}}, -    {"mips", {ELF::EM_MIPS, false, false}}, -    {"powerpc:common64", {ELF::EM_PPC64, true, true}}, -    {"riscv:rv32", {ELF::EM_RISCV, false, true}}, -    {"riscv:rv64", {ELF::EM_RISCV, true, true}}, -    {"sparc", {ELF::EM_SPARC, false, false}}, -    {"sparcel", {ELF::EM_SPARC, false, true}}, -    {"x86-64", {ELF::EM_X86_64, true, true}}, -}; - -static Expected<const MachineInfo &> getMachineInfo(StringRef Arch) { -  auto Iter = ArchMap.find(Arch); -  if (Iter == std::end(ArchMap)) -    return createStringError(errc::invalid_argument, -                             "invalid architecture: '%s'", Arch.str().c_str()); -  return Iter->getValue(); -} -  struct TargetInfo {    FileFormat Format;    MachineInfo Machine; @@ -341,9 +298,10 @@ getOutputTargetInfoByTargetName(StringRef TargetName) {    return {TargetInfo{Format, MI}};  } -static Error addSymbolsFromFile(std::vector<NameOrRegex> &Symbols, -                                BumpPtrAllocator &Alloc, StringRef Filename, -                                bool UseRegex) { +static Error +addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc, +                   StringRef Filename, MatchStyle MS, +                   llvm::function_ref<Error(Error)> ErrorCallback) {    StringSaver Saver(Alloc);    SmallVector<StringRef, 16> Lines;    auto BufOrErr = MemoryBuffer::getFile(Filename); @@ -356,21 +314,47 @@ static Error addSymbolsFromFile(std::vector<NameOrRegex> &Symbols,      // it's not empty.      auto TrimmedLine = Line.split('#').first.trim();      if (!TrimmedLine.empty()) -      Symbols.emplace_back(Saver.save(TrimmedLine), UseRegex); +      if (Error E = Symbols.addMatcher(NameOrPattern::create( +              Saver.save(TrimmedLine), MS, ErrorCallback))) +        return E;    }    return Error::success();  } -NameOrRegex::NameOrRegex(StringRef Pattern, bool IsRegex) { -  if (!IsRegex) { -    Name = Pattern; -    return; -  } +Expected<NameOrPattern> +NameOrPattern::create(StringRef Pattern, MatchStyle MS, +                      llvm::function_ref<Error(Error)> ErrorCallback) { +  switch (MS) { +  case MatchStyle::Literal: +    return NameOrPattern(Pattern); +  case MatchStyle::Wildcard: { +    SmallVector<char, 32> Data; +    bool IsPositiveMatch = true; +    if (Pattern[0] == '!') { +      IsPositiveMatch = false; +      Pattern = Pattern.drop_front(); +    } +    Expected<GlobPattern> GlobOrErr = GlobPattern::create(Pattern); + +    // If we couldn't create it as a glob, report the error, but try again with +    // a literal if the error reporting is non-fatal. +    if (!GlobOrErr) { +      if (Error E = ErrorCallback(GlobOrErr.takeError())) +        return std::move(E); +      return create(Pattern, MatchStyle::Literal, ErrorCallback); +    } -  SmallVector<char, 32> Data; -  R = std::make_shared<Regex>( -      ("^" + Pattern.ltrim('^').rtrim('$') + "$").toStringRef(Data)); +    return NameOrPattern(std::make_shared<GlobPattern>(*GlobOrErr), +                         IsPositiveMatch); +  } +  case MatchStyle::Regex: { +    SmallVector<char, 32> Data; +    return NameOrPattern(std::make_shared<Regex>( +        ("^" + Pattern.ltrim('^').rtrim('$') + "$").toStringRef(Data))); +  } +  } +  llvm_unreachable("Unhandled llvm.objcopy.MatchStyle enum");  }  static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename, @@ -407,10 +391,22 @@ template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {    return Result;  } +static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS, +                      StringRef ToolName) { +  OptTable.PrintHelp(OS, (ToolName + " input [output]").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"; +} +  // 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> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) { +Expected<DriverConfig> +parseObjcopyOptions(ArrayRef<const char *> ArgsArr, +                    llvm::function_ref<Error(Error)> ErrorCallback) {    DriverConfig DC;    ObjcopyOptTable T;    unsigned MissingArgumentIndex, MissingArgumentCount; @@ -418,12 +414,12 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {        T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);    if (InputArgs.size() == 0) { -    T.PrintHelp(errs(), "llvm-objcopy input [output]", "objcopy tool"); +    printHelp(T, errs(), "llvm-objcopy");      exit(1);    }    if (InputArgs.hasArg(OBJCOPY_help)) { -    T.PrintHelp(outs(), "llvm-objcopy input [output]", "objcopy tool"); +    printHelp(T, outs(), "llvm-objcopy");      exit(0);    } @@ -459,7 +455,18 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {          errc::invalid_argument,          "--target cannot be used with --input-target or --output-target"); -  bool UseRegex = InputArgs.hasArg(OBJCOPY_regex); +  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); @@ -476,28 +483,26 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {                             .Case("binary", FileFormat::Binary)                             .Case("ihex", FileFormat::IHex)                             .Default(FileFormat::Unspecified); -  if (Config.InputFormat == FileFormat::Binary) { -    auto BinaryArch = InputArgs.getLastArgValue(OBJCOPY_binary_architecture); -    if (BinaryArch.empty()) -      return createStringError( -          errc::invalid_argument, -          "specified binary input without specifiying an architecture"); -    Expected<const MachineInfo &> MI = getMachineInfo(BinaryArch); -    if (!MI) -      return MI.takeError(); -    Config.BinaryArch = *MI; -  } + +  if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) +    Config.NewSymbolVisibility = +        InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);    Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)                              .Case("binary", FileFormat::Binary)                              .Case("ihex", FileFormat::IHex)                              .Default(FileFormat::Unspecified); -  if (Config.OutputFormat == FileFormat::Unspecified && !OutputFormat.empty()) { -    Expected<TargetInfo> Target = getOutputTargetInfoByTargetName(OutputFormat); -    if (!Target) -      return Target.takeError(); -    Config.OutputFormat = Target->Format; -    Config.OutputArch = Target->Machine; +  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 (auto Arg = InputArgs.getLastArg(OBJCOPY_compress_debug_sections, @@ -535,12 +540,8 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {      if (!DebugOrErr)        return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());      auto Debug = std::move(*DebugOrErr); -    JamCRC CRC; -    CRC.update( -        ArrayRef<char>(Debug->getBuffer().data(), Debug->getBuffer().size())); -    // The CRC32 value needs to be complemented because the JamCRC doesn't -    // finalize the CRC32 value. -    Config.GnuDebugLinkCRC32 = ~CRC.getCRC(); +    Config.GnuDebugLinkCRC32 = +        llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));    }    Config.BuildIdLinkDir = InputArgs.getLastArgValue(OBJCOPY_build_id_link_dir);    if (InputArgs.hasArg(OBJCOPY_build_id_link_input)) @@ -582,6 +583,13 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {                                 "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 = +        parseSetSectionAlignment(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()); @@ -612,13 +620,28 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {    }    for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section)) -    Config.ToRemove.emplace_back(Arg->getValue(), UseRegex); +    if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( +            Arg->getValue(), SectionMatchStyle, ErrorCallback))) +      return std::move(E);    for (auto Arg : InputArgs.filtered(OBJCOPY_keep_section)) -    Config.KeepSection.emplace_back(Arg->getValue(), UseRegex); +    if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( +            Arg->getValue(), SectionMatchStyle, ErrorCallback))) +      return std::move(E);    for (auto Arg : InputArgs.filtered(OBJCOPY_only_section)) -    Config.OnlySection.emplace_back(Arg->getValue(), UseRegex); -  for (auto Arg : InputArgs.filtered(OBJCOPY_add_section)) -    Config.AddSection.push_back(Arg->getValue()); +    if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create( +            Arg->getValue(), SectionMatchStyle, ErrorCallback))) +      return std::move(E); +  for (auto Arg : InputArgs.filtered(OBJCOPY_add_section)) { +    StringRef ArgValue(Arg->getValue()); +    if (!ArgValue.contains('=')) +      return createStringError(errc::invalid_argument, +                               "bad format for --add-section: missing '='"); +    if (ArgValue.split("=").second.empty()) +      return createStringError( +          errc::invalid_argument, +          "bad format for --add-section: missing file name"); +    Config.AddSection.push_back(ArgValue); +  }    for (auto Arg : InputArgs.filtered(OBJCOPY_dump_section))      Config.DumpSection.push_back(Arg->getValue());    Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all); @@ -645,53 +668,71 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {    if (Config.DiscardMode == DiscardType::All)      Config.StripDebug = true;    for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol)) -    Config.SymbolsToLocalize.emplace_back(Arg->getValue(), UseRegex); +    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(), UseRegex)) +                                     Arg->getValue(), SymbolMatchStyle, +                                     ErrorCallback))        return std::move(E);    for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol)) -    Config.SymbolsToKeepGlobal.emplace_back(Arg->getValue(), UseRegex); +    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(), UseRegex)) +                                     Arg->getValue(), SymbolMatchStyle, +                                     ErrorCallback))        return std::move(E);    for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol)) -    Config.SymbolsToGlobalize.emplace_back(Arg->getValue(), UseRegex); +    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(), UseRegex)) +                                     Arg->getValue(), SymbolMatchStyle, +                                     ErrorCallback))        return std::move(E);    for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol)) -    Config.SymbolsToWeaken.emplace_back(Arg->getValue(), UseRegex); +    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(), UseRegex)) +                                     Arg->getValue(), SymbolMatchStyle, +                                     ErrorCallback))        return std::move(E);    for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol)) -    Config.SymbolsToRemove.emplace_back(Arg->getValue(), UseRegex); +    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(), UseRegex)) +                                     Arg->getValue(), SymbolMatchStyle, +                                     ErrorCallback))        return std::move(E);    for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol)) -    Config.UnneededSymbolsToRemove.emplace_back(Arg->getValue(), UseRegex); +    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(), UseRegex)) +                                     Arg->getValue(), SymbolMatchStyle, +                                     ErrorCallback))        return std::move(E);    for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol)) -    Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegex); +    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(), UseRegex)) +    if (Error E = +            addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(), +                               SymbolMatchStyle, ErrorCallback))        return std::move(E); -  for (auto Arg : InputArgs.filtered(OBJCOPY_add_symbol)) { -    Expected<NewSymbolInfo> NSI = parseNewSymbolInfo(Arg->getValue()); -    if (!NSI) -      return NSI.takeError(); -    Config.SymbolsToAdd.push_back(*NSI); -  } +  for (auto Arg : InputArgs.filtered(OBJCOPY_add_symbol)) +    Config.SymbolsToAdd.push_back(Arg->getValue());    Config.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links); @@ -749,24 +790,75 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {    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> +parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) { +  DriverConfig DC; +  CopyConfig Config; +  InstallNameToolOptTable T; +  unsigned MissingArgumentIndex, MissingArgumentCount; +  llvm::opt::InputArgList InputArgs = +      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); + +  if (InputArgs.size() == 0) { +    printHelp(T, errs(), "llvm-install-name-tool"); +    exit(1); +  } + +  if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) { +    printHelp(T, outs(), "llvm-install-name-tool"); +    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)) +    Config.RPathToAdd.push_back(Arg->getValue()); + +  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 = Positional[0]; + +  DC.CopyConfigs.push_back(std::move(Config)); +  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>  parseStripOptions(ArrayRef<const char *> ArgsArr, -                  std::function<Error(Error)> ErrorCallback) { +                  llvm::function_ref<Error(Error)> ErrorCallback) {    StripOptTable T;    unsigned MissingArgumentIndex, MissingArgumentCount;    llvm::opt::InputArgList InputArgs =        T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);    if (InputArgs.size() == 0) { -    T.PrintHelp(errs(), "llvm-strip [options] file...", "strip tool"); +    printHelp(T, errs(), "llvm-strip");      exit(1);    }    if (InputArgs.hasArg(STRIP_help)) { -    T.PrintHelp(outs(), "llvm-strip [options] file...", "strip tool"); +    printHelp(T, outs(), "llvm-strip");      exit(0);    } @@ -792,7 +884,17 @@ parseStripOptions(ArrayRef<const char *> ArgsArr,          "multiple input files cannot be used in combination with -o");    CopyConfig Config; -  bool UseRegexp = InputArgs.hasArg(STRIP_regex); + +  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;    Config.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);    Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug); @@ -801,6 +903,7 @@ parseStripOptions(ArrayRef<const char *> ArgsArr,          InputArgs.hasFlag(STRIP_discard_all, STRIP_discard_locals)              ? 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; @@ -809,16 +912,24 @@ parseStripOptions(ArrayRef<const char *> ArgsArr,    Config.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);    for (auto Arg : InputArgs.filtered(STRIP_keep_section)) -    Config.KeepSection.emplace_back(Arg->getValue(), UseRegexp); +    if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( +            Arg->getValue(), SectionMatchStyle, ErrorCallback))) +      return std::move(E);    for (auto Arg : InputArgs.filtered(STRIP_remove_section)) -    Config.ToRemove.emplace_back(Arg->getValue(), UseRegexp); +    if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( +            Arg->getValue(), SectionMatchStyle, ErrorCallback))) +      return std::move(E);    for (auto Arg : InputArgs.filtered(STRIP_strip_symbol)) -    Config.SymbolsToRemove.emplace_back(Arg->getValue(), UseRegexp); +    if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( +            Arg->getValue(), SymbolMatchStyle, ErrorCallback))) +      return std::move(E);    for (auto Arg : InputArgs.filtered(STRIP_keep_symbol)) -    Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegexp); +    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.StripUnneeded && Config.DiscardMode == DiscardType::None &&  | 
