brintos

brintos / llvm-project-archived public Read only

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