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