1 //===- ObjcopyOptions.cpp -------------------------------------------------===//
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
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"
28 using namespace llvm::objcopy
;
29 using namespace llvm::opt
;
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"
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"
47 static constexpr opt::OptTable::Info ObjcopyInfoTable
[] = {
49 LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
50 #include "ObjcopyOpts.inc"
53 } // namespace objcopy_opt
55 class ObjcopyOptTable
: public opt::GenericOptTable
{
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.
65 LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
66 #include "InstallNameToolOpts.inc"
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"
79 static constexpr opt::OptTable::Info InstallNameToolInfoTable
[] = {
81 LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
82 #include "InstallNameToolOpts.inc"
85 } // namespace install_name_tool
87 class InstallNameToolOptTable
: public opt::GenericOptTable
{
89 InstallNameToolOptTable()
90 : GenericOptTable(install_name_tool::InstallNameToolInfoTable
) {}
94 BITCODE_STRIP_INVALID
= 0, // This is not an option ID.
96 LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
97 #include "BitcodeStripOpts.inc"
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"
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"
116 } // namespace bitcode_strip
118 class BitcodeStripOptTable
: public opt::GenericOptTable
{
120 BitcodeStripOptTable()
121 : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable
) {}
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"
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"
139 static constexpr opt::OptTable::Info StripInfoTable
[] = {
140 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
141 #include "StripOpts.inc"
146 class StripOptTable
: public opt::GenericOptTable
{
148 StripOptTable() : GenericOptTable(strip::StripInfoTable
) {
149 setGroupedShortOptions(true);
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",
186 ParsedFlags
|= ParsedFlag
;
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('=');
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());
211 return ParsedFlagSet
.takeError();
212 SR
.NewFlags
= *ParsedFlagSet
;
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
);
229 if (Split
.second
.getAsInteger(0, Value
))
230 return make_error
<StringError
>("invalid value for " + Option
+ ": '" +
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
);
252 return ParsedFlagSet
.takeError();
253 SFU
.NewFlags
= *ParsedFlagSet
;
265 // FIXME: consolidate with the bfd parsing used by lld.
266 static const StringMap
<MachineInfo
> TargetMap
{
267 // Name, {EMachine, 64bit, LittleEndian}
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}},
273 {"elf32-iamcu", {ELF::EM_IAMCU
, false, true}},
275 {"elf32-littlearm", {ELF::EM_ARM
, false, true}},
277 {"elf64-aarch64", {ELF::EM_AARCH64
, true, true}},
278 {"elf64-littleaarch64", {ELF::EM_AARCH64
, true, true}},
280 {"elf32-littleriscv", {ELF::EM_RISCV
, false, true}},
281 {"elf64-littleriscv", {ELF::EM_RISCV
, true, true}},
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}},
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}},
296 {"elf32-sparc", {ELF::EM_SPARC
, false, false}},
297 {"elf32-sparcel", {ELF::EM_SPARC
, false, true}},
299 {"elf32-hexagon", {ELF::EM_HEXAGON
, false, true}},
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();
316 MI
.OSABI
= ELF::ELFOSABI_FREEBSD
;
319 if (TargetName
.startswith("elf"))
320 Format
= FileFormat::ELF
;
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
);
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
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
)))
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
);
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())
368 std::pair
<StringRef
, StringRef
> Pair
= Saver
.save(TrimmedLine
).split(' ');
369 StringRef NewName
= Pair
.second
.trim();
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
) {
381 if (Val
.getAsInteger(0, Result
))
382 return errc::invalid_argument
;
388 enum class ToolType
{ Objcopy
, Strip
, InstallNameTool
, BitcodeStrip
};
390 } // anonymous namespace
392 static void printHelp(const opt::OptTable
&OptTable
, raw_ostream
&OS
,
394 StringRef HelpText
, ToolName
;
396 case ToolType::Objcopy
:
397 ToolName
= "llvm-objcopy";
398 HelpText
= " [options] input [output]";
400 case ToolType::Strip
:
401 ToolName
= "llvm-strip";
402 HelpText
= " [options] inputs...";
404 case ToolType::InstallNameTool
:
405 ToolName
= "llvm-install-name-tool";
406 HelpText
= " [options] input";
408 case ToolType::BitcodeStrip
:
409 ToolName
= "llvm-bitcode-strip";
410 HelpText
= " [options] input";
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>]
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
432 // <flags> - optional flags affecting symbol type, binding or visibility.
435 std::tie(SI
.SymbolName
, Value
) = FlagValue
.split('=');
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
])
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
); })
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
); })
475 [&] { SI
.Flags
.push_back(SymbolFlag::Object
); })
476 .CaseLower("function",
477 [&] { SI
.Flags
.push_back(SymbolFlag::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=",
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());
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 " +
524 ": missing file name");
526 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> BufOrErr
=
527 MemoryBuffer::getFile(SecPair
.second
);
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
539 Expected
<DriverConfig
>
540 objcopy::parseObjcopyOptions(ArrayRef
<const char *> RawArgsArr
,
541 function_ref
<Error(Error
)> ErrorCallback
) {
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
);
560 if (InputArgs
.hasArg(OBJCOPY_help
)) {
561 printHelp(T
, outs(), ToolType::Objcopy
);
565 if (InputArgs
.hasArg(OBJCOPY_version
)) {
566 outs() << "llvm-objcopy, compatible with GNU objcopy\n";
567 cl::PrintVersionMessage();
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
)
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
);
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
)
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('.');
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
;
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
;
696 Expected
<TargetInfo
> Target
=
697 getOutputTargetInfoByTargetName(OutputFormat
);
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",
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
);
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
,
757 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_rename_section
)) {
758 Expected
<SectionRename
> SR
=
759 parseRenameSectionValue(StringRef(Arg
->getValue()));
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());
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());
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());
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
))
805 if (Config
.SetSectionType
.count(SR
.NewName
))
809 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_remove_section
))
810 if (Error E
= Config
.ToRemove
.addMatcher(NameOrPattern::create(
811 Arg
->getValue(), SectionMatchStyle
, ErrorCallback
)))
813 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_keep_section
))
814 if (Error E
= Config
.KeepSection
.addMatcher(NameOrPattern::create(
815 Arg
->getValue(), SectionMatchStyle
, ErrorCallback
)))
817 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_only_section
))
818 if (Error E
= Config
.OnlySection
.addMatcher(NameOrPattern::create(
819 Arg
->getValue(), SectionMatchStyle
, ErrorCallback
)))
821 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_add_section
)) {
822 if (Error Err
= loadNewSectionData(Arg
->getValue(), "--add-section",
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
);
852 InputArgs
.getLastArg(OBJCOPY_discard_all
, OBJCOPY_discard_locals
)) {
853 Config
.DiscardMode
= Arg
->getOption().matches(OBJCOPY_discard_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
)))
870 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_localize_symbols
))
871 if (Error E
= addSymbolsFromFile(Config
.SymbolsToLocalize
, DC
.Alloc
,
872 Arg
->getValue(), SymbolMatchStyle
,
875 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_keep_global_symbol
))
876 if (Error E
= Config
.SymbolsToKeepGlobal
.addMatcher(NameOrPattern::create(
877 Arg
->getValue(), SymbolMatchStyle
, ErrorCallback
)))
879 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_keep_global_symbols
))
880 if (Error E
= addSymbolsFromFile(Config
.SymbolsToKeepGlobal
, DC
.Alloc
,
881 Arg
->getValue(), SymbolMatchStyle
,
884 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_globalize_symbol
))
885 if (Error E
= Config
.SymbolsToGlobalize
.addMatcher(NameOrPattern::create(
886 Arg
->getValue(), SymbolMatchStyle
, ErrorCallback
)))
888 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_globalize_symbols
))
889 if (Error E
= addSymbolsFromFile(Config
.SymbolsToGlobalize
, DC
.Alloc
,
890 Arg
->getValue(), SymbolMatchStyle
,
893 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_weaken_symbol
))
894 if (Error E
= Config
.SymbolsToWeaken
.addMatcher(NameOrPattern::create(
895 Arg
->getValue(), SymbolMatchStyle
, ErrorCallback
)))
897 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_weaken_symbols
))
898 if (Error E
= addSymbolsFromFile(Config
.SymbolsToWeaken
, DC
.Alloc
,
899 Arg
->getValue(), SymbolMatchStyle
,
902 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_strip_symbol
))
903 if (Error E
= Config
.SymbolsToRemove
.addMatcher(NameOrPattern::create(
904 Arg
->getValue(), SymbolMatchStyle
, ErrorCallback
)))
906 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_strip_symbols
))
907 if (Error E
= addSymbolsFromFile(Config
.SymbolsToRemove
, DC
.Alloc
,
908 Arg
->getValue(), SymbolMatchStyle
,
911 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_strip_unneeded_symbol
))
913 Config
.UnneededSymbolsToRemove
.addMatcher(NameOrPattern::create(
914 Arg
->getValue(), SymbolMatchStyle
, ErrorCallback
)))
916 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_strip_unneeded_symbols
))
917 if (Error E
= addSymbolsFromFile(Config
.UnneededSymbolsToRemove
, DC
.Alloc
,
918 Arg
->getValue(), SymbolMatchStyle
,
921 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_keep_symbol
))
922 if (Error E
= Config
.SymbolsToKeep
.addMatcher(NameOrPattern::create(
923 Arg
->getValue(), SymbolMatchStyle
, ErrorCallback
)))
925 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_keep_symbols
))
927 addSymbolsFromFile(Config
.SymbolsToKeep
, DC
.Alloc
, Arg
->getValue(),
928 SymbolMatchStyle
, ErrorCallback
))
930 for (auto *Arg
: InputArgs
.filtered(OBJCOPY_add_symbol
)) {
931 Expected
<NewSymbolInfo
> SymInfo
= parseNewSymbolInfo(Arg
->getValue());
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());
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());
962 return createStringError(EIncr
.getError(),
963 "bad entry point increment: '%s'",
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
992 Expected
<DriverConfig
>
993 objcopy::parseInstallNameToolOptions(ArrayRef
<const char *> ArgsArr
) {
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
)) +
1010 if (InputArgs
.size() == 0) {
1011 printHelp(T
, errs(), ToolType::InstallNameTool
);
1015 if (InputArgs
.hasArg(INSTALL_NAME_TOOL_help
)) {
1016 printHelp(T
, outs(), ToolType::InstallNameTool
);
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();
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
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
) {
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
);
1143 if (InputArgs
.hasArg(BITCODE_STRIP_help
)) {
1144 printHelp(T
, outs(), ToolType::BitcodeStrip
);
1148 if (InputArgs
.hasArg(BITCODE_STRIP_version
)) {
1149 outs() << "llvm-bitcode-strip, compatible with cctools "
1151 cl::PrintVersionMessage();
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
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
);
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
);
1217 if (InputArgs
.hasArg(STRIP_help
)) {
1218 printHelp(T
, outs(), ToolType::Strip
);
1222 if (InputArgs
.hasArg(STRIP_version
)) {
1223 outs() << "llvm-strip, compatible with GNU strip\n";
1224 cl::PrintVersionMessage();
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
)
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
;
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
));
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
);