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