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