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