181ad6265SDimitry Andric //===- ObjcopyOptions.cpp -------------------------------------------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "ObjcopyOptions.h" 1081ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 1106c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 1281ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 13*0fca6ea1SDimitry Andric #include "llvm/ADT/StringSwitch.h" 1481ad6265SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 1581ad6265SDimitry Andric #include "llvm/ObjCopy/CommonConfig.h" 1681ad6265SDimitry Andric #include "llvm/ObjCopy/ConfigManager.h" 1781ad6265SDimitry Andric #include "llvm/ObjCopy/MachO/MachOConfig.h" 18*0fca6ea1SDimitry Andric #include "llvm/Object/Binary.h" 1981ad6265SDimitry Andric #include "llvm/Option/Arg.h" 2081ad6265SDimitry Andric #include "llvm/Option/ArgList.h" 2181ad6265SDimitry Andric #include "llvm/Support/CRC.h" 2281ad6265SDimitry Andric #include "llvm/Support/CommandLine.h" 2381ad6265SDimitry Andric #include "llvm/Support/Compression.h" 2481ad6265SDimitry Andric #include "llvm/Support/Errc.h" 2581ad6265SDimitry Andric #include "llvm/Support/Error.h" 2681ad6265SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric using namespace llvm; 2981ad6265SDimitry Andric using namespace llvm::objcopy; 30*0fca6ea1SDimitry Andric using namespace llvm::object; 315f757f3fSDimitry Andric using namespace llvm::opt; 3281ad6265SDimitry Andric 3381ad6265SDimitry Andric namespace { 3481ad6265SDimitry Andric enum ObjcopyID { 3581ad6265SDimitry Andric OBJCOPY_INVALID = 0, // This is not an option ID. 365f757f3fSDimitry Andric #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__), 3781ad6265SDimitry Andric #include "ObjcopyOpts.inc" 3881ad6265SDimitry Andric #undef OPTION 3981ad6265SDimitry Andric }; 4081ad6265SDimitry Andric 41bdd1243dSDimitry Andric namespace objcopy_opt { 42bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE) \ 43bdd1243dSDimitry Andric static constexpr StringLiteral NAME##_init[] = VALUE; \ 44bdd1243dSDimitry Andric static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ 45bdd1243dSDimitry Andric std::size(NAME##_init) - 1); 4681ad6265SDimitry Andric #include "ObjcopyOpts.inc" 4781ad6265SDimitry Andric #undef PREFIX 4881ad6265SDimitry Andric 49bdd1243dSDimitry Andric static constexpr opt::OptTable::Info ObjcopyInfoTable[] = { 505f757f3fSDimitry Andric #define OPTION(...) \ 515f757f3fSDimitry Andric LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__), 5281ad6265SDimitry Andric #include "ObjcopyOpts.inc" 5381ad6265SDimitry Andric #undef OPTION 5481ad6265SDimitry Andric }; 55bdd1243dSDimitry Andric } // namespace objcopy_opt 5681ad6265SDimitry Andric 57bdd1243dSDimitry Andric class ObjcopyOptTable : public opt::GenericOptTable { 5881ad6265SDimitry Andric public: 59bdd1243dSDimitry Andric ObjcopyOptTable() : opt::GenericOptTable(objcopy_opt::ObjcopyInfoTable) { 6081ad6265SDimitry Andric setGroupedShortOptions(true); 6181ad6265SDimitry Andric } 6281ad6265SDimitry Andric }; 6381ad6265SDimitry Andric 6481ad6265SDimitry Andric enum InstallNameToolID { 6581ad6265SDimitry Andric INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID. 665f757f3fSDimitry Andric #define OPTION(...) \ 675f757f3fSDimitry Andric LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__), 6881ad6265SDimitry Andric #include "InstallNameToolOpts.inc" 6981ad6265SDimitry Andric #undef OPTION 7081ad6265SDimitry Andric }; 7181ad6265SDimitry Andric 72bdd1243dSDimitry Andric namespace install_name_tool { 73bdd1243dSDimitry Andric 7481ad6265SDimitry Andric #define PREFIX(NAME, VALUE) \ 75bdd1243dSDimitry Andric static constexpr StringLiteral NAME##_init[] = VALUE; \ 76bdd1243dSDimitry Andric static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ 77bdd1243dSDimitry Andric std::size(NAME##_init) - 1); 7881ad6265SDimitry Andric #include "InstallNameToolOpts.inc" 7981ad6265SDimitry Andric #undef PREFIX 8081ad6265SDimitry Andric 81bdd1243dSDimitry Andric static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = { 825f757f3fSDimitry Andric #define OPTION(...) \ 835f757f3fSDimitry Andric LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__), 8481ad6265SDimitry Andric #include "InstallNameToolOpts.inc" 8581ad6265SDimitry Andric #undef OPTION 8681ad6265SDimitry Andric }; 87bdd1243dSDimitry Andric } // namespace install_name_tool 8881ad6265SDimitry Andric 89bdd1243dSDimitry Andric class InstallNameToolOptTable : public opt::GenericOptTable { 9081ad6265SDimitry Andric public: 91bdd1243dSDimitry Andric InstallNameToolOptTable() 92bdd1243dSDimitry Andric : GenericOptTable(install_name_tool::InstallNameToolInfoTable) {} 9381ad6265SDimitry Andric }; 9481ad6265SDimitry Andric 9581ad6265SDimitry Andric enum BitcodeStripID { 9681ad6265SDimitry Andric BITCODE_STRIP_INVALID = 0, // This is not an option ID. 975f757f3fSDimitry Andric #define OPTION(...) \ 985f757f3fSDimitry Andric LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__), 9981ad6265SDimitry Andric #include "BitcodeStripOpts.inc" 10081ad6265SDimitry Andric #undef OPTION 10181ad6265SDimitry Andric }; 10281ad6265SDimitry Andric 103bdd1243dSDimitry Andric namespace bitcode_strip { 104bdd1243dSDimitry Andric 105bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE) \ 106bdd1243dSDimitry Andric static constexpr StringLiteral NAME##_init[] = VALUE; \ 107bdd1243dSDimitry Andric static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ 108bdd1243dSDimitry Andric std::size(NAME##_init) - 1); 10981ad6265SDimitry Andric #include "BitcodeStripOpts.inc" 11081ad6265SDimitry Andric #undef PREFIX 11181ad6265SDimitry Andric 112bdd1243dSDimitry Andric static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = { 1135f757f3fSDimitry Andric #define OPTION(...) \ 1145f757f3fSDimitry Andric LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__), 11581ad6265SDimitry Andric #include "BitcodeStripOpts.inc" 11681ad6265SDimitry Andric #undef OPTION 11781ad6265SDimitry Andric }; 118bdd1243dSDimitry Andric } // namespace bitcode_strip 11981ad6265SDimitry Andric 120bdd1243dSDimitry Andric class BitcodeStripOptTable : public opt::GenericOptTable { 12181ad6265SDimitry Andric public: 122bdd1243dSDimitry Andric BitcodeStripOptTable() 123bdd1243dSDimitry Andric : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable) {} 12481ad6265SDimitry Andric }; 12581ad6265SDimitry Andric 12681ad6265SDimitry Andric enum StripID { 12781ad6265SDimitry Andric STRIP_INVALID = 0, // This is not an option ID. 1285f757f3fSDimitry Andric #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__), 12981ad6265SDimitry Andric #include "StripOpts.inc" 13081ad6265SDimitry Andric #undef OPTION 13181ad6265SDimitry Andric }; 13281ad6265SDimitry Andric 133bdd1243dSDimitry Andric namespace strip { 134bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE) \ 135bdd1243dSDimitry Andric static constexpr StringLiteral NAME##_init[] = VALUE; \ 136bdd1243dSDimitry Andric static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ 137bdd1243dSDimitry Andric std::size(NAME##_init) - 1); 13881ad6265SDimitry Andric #include "StripOpts.inc" 13981ad6265SDimitry Andric #undef PREFIX 14081ad6265SDimitry Andric 141bdd1243dSDimitry Andric static constexpr opt::OptTable::Info StripInfoTable[] = { 1425f757f3fSDimitry Andric #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__), 14381ad6265SDimitry Andric #include "StripOpts.inc" 14481ad6265SDimitry Andric #undef OPTION 14581ad6265SDimitry Andric }; 146bdd1243dSDimitry Andric } // namespace strip 14781ad6265SDimitry Andric 148bdd1243dSDimitry Andric class StripOptTable : public opt::GenericOptTable { 14981ad6265SDimitry Andric public: 150bdd1243dSDimitry Andric StripOptTable() : GenericOptTable(strip::StripInfoTable) { 151bdd1243dSDimitry Andric setGroupedShortOptions(true); 152bdd1243dSDimitry Andric } 15381ad6265SDimitry Andric }; 15481ad6265SDimitry Andric 15581ad6265SDimitry Andric } // namespace 15681ad6265SDimitry Andric 15781ad6265SDimitry Andric static SectionFlag parseSectionRenameFlag(StringRef SectionName) { 15881ad6265SDimitry Andric return llvm::StringSwitch<SectionFlag>(SectionName) 15981ad6265SDimitry Andric .CaseLower("alloc", SectionFlag::SecAlloc) 16081ad6265SDimitry Andric .CaseLower("load", SectionFlag::SecLoad) 16181ad6265SDimitry Andric .CaseLower("noload", SectionFlag::SecNoload) 16281ad6265SDimitry Andric .CaseLower("readonly", SectionFlag::SecReadonly) 16381ad6265SDimitry Andric .CaseLower("debug", SectionFlag::SecDebug) 16481ad6265SDimitry Andric .CaseLower("code", SectionFlag::SecCode) 16581ad6265SDimitry Andric .CaseLower("data", SectionFlag::SecData) 16681ad6265SDimitry Andric .CaseLower("rom", SectionFlag::SecRom) 16781ad6265SDimitry Andric .CaseLower("merge", SectionFlag::SecMerge) 16881ad6265SDimitry Andric .CaseLower("strings", SectionFlag::SecStrings) 16981ad6265SDimitry Andric .CaseLower("contents", SectionFlag::SecContents) 17081ad6265SDimitry Andric .CaseLower("share", SectionFlag::SecShare) 17181ad6265SDimitry Andric .CaseLower("exclude", SectionFlag::SecExclude) 1725f757f3fSDimitry Andric .CaseLower("large", SectionFlag::SecLarge) 17381ad6265SDimitry Andric .Default(SectionFlag::SecNone); 17481ad6265SDimitry Andric } 17581ad6265SDimitry Andric 17681ad6265SDimitry Andric static Expected<SectionFlag> 17781ad6265SDimitry Andric parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) { 17881ad6265SDimitry Andric SectionFlag ParsedFlags = SectionFlag::SecNone; 17981ad6265SDimitry Andric for (StringRef Flag : SectionFlags) { 18081ad6265SDimitry Andric SectionFlag ParsedFlag = parseSectionRenameFlag(Flag); 18181ad6265SDimitry Andric if (ParsedFlag == SectionFlag::SecNone) 18281ad6265SDimitry Andric return createStringError( 18381ad6265SDimitry Andric errc::invalid_argument, 18481ad6265SDimitry Andric "unrecognized section flag '%s'. Flags supported for GNU " 18581ad6265SDimitry Andric "compatibility: alloc, load, noload, readonly, exclude, debug, " 1865f757f3fSDimitry Andric "code, data, rom, share, contents, merge, strings, large", 18781ad6265SDimitry Andric Flag.str().c_str()); 18881ad6265SDimitry Andric ParsedFlags |= ParsedFlag; 18981ad6265SDimitry Andric } 19081ad6265SDimitry Andric 19181ad6265SDimitry Andric return ParsedFlags; 19281ad6265SDimitry Andric } 19381ad6265SDimitry Andric 19481ad6265SDimitry Andric static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) { 19581ad6265SDimitry Andric if (!FlagValue.contains('=')) 19681ad6265SDimitry Andric return createStringError(errc::invalid_argument, 19781ad6265SDimitry Andric "bad format for --rename-section: missing '='"); 19881ad6265SDimitry Andric 19981ad6265SDimitry Andric // Initial split: ".foo" = ".bar,f1,f2,..." 20081ad6265SDimitry Andric auto Old2New = FlagValue.split('='); 20181ad6265SDimitry Andric SectionRename SR; 20281ad6265SDimitry Andric SR.OriginalName = Old2New.first; 20381ad6265SDimitry Andric 20481ad6265SDimitry Andric // Flags split: ".bar" "f1" "f2" ... 20581ad6265SDimitry Andric SmallVector<StringRef, 6> NameAndFlags; 20681ad6265SDimitry Andric Old2New.second.split(NameAndFlags, ','); 20781ad6265SDimitry Andric SR.NewName = NameAndFlags[0]; 20881ad6265SDimitry Andric 20981ad6265SDimitry Andric if (NameAndFlags.size() > 1) { 21081ad6265SDimitry Andric Expected<SectionFlag> ParsedFlagSet = 211bdd1243dSDimitry Andric parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front()); 21281ad6265SDimitry Andric if (!ParsedFlagSet) 21381ad6265SDimitry Andric return ParsedFlagSet.takeError(); 21481ad6265SDimitry Andric SR.NewFlags = *ParsedFlagSet; 21581ad6265SDimitry Andric } 21681ad6265SDimitry Andric 21781ad6265SDimitry Andric return SR; 21881ad6265SDimitry Andric } 21981ad6265SDimitry Andric 22081ad6265SDimitry Andric static Expected<std::pair<StringRef, uint64_t>> 221753f127fSDimitry Andric parseSetSectionAttribute(StringRef Option, StringRef FlagValue) { 22281ad6265SDimitry Andric if (!FlagValue.contains('=')) 223753f127fSDimitry Andric return make_error<StringError>("bad format for " + Option + ": missing '='", 224753f127fSDimitry Andric errc::invalid_argument); 22581ad6265SDimitry Andric auto Split = StringRef(FlagValue).split('='); 22681ad6265SDimitry Andric if (Split.first.empty()) 227753f127fSDimitry Andric return make_error<StringError>("bad format for " + Option + 228753f127fSDimitry Andric ": missing section name", 229753f127fSDimitry Andric errc::invalid_argument); 230753f127fSDimitry Andric uint64_t Value; 231753f127fSDimitry Andric if (Split.second.getAsInteger(0, Value)) 232753f127fSDimitry Andric return make_error<StringError>("invalid value for " + Option + ": '" + 233753f127fSDimitry Andric Split.second + "'", 234753f127fSDimitry Andric errc::invalid_argument); 235753f127fSDimitry Andric return std::make_pair(Split.first, Value); 23681ad6265SDimitry Andric } 23781ad6265SDimitry Andric 23881ad6265SDimitry Andric static Expected<SectionFlagsUpdate> 23981ad6265SDimitry Andric parseSetSectionFlagValue(StringRef FlagValue) { 24081ad6265SDimitry Andric if (!StringRef(FlagValue).contains('=')) 24181ad6265SDimitry Andric return createStringError(errc::invalid_argument, 24281ad6265SDimitry Andric "bad format for --set-section-flags: missing '='"); 24381ad6265SDimitry Andric 24481ad6265SDimitry Andric // Initial split: ".foo" = "f1,f2,..." 24581ad6265SDimitry Andric auto Section2Flags = StringRef(FlagValue).split('='); 24681ad6265SDimitry Andric SectionFlagsUpdate SFU; 24781ad6265SDimitry Andric SFU.Name = Section2Flags.first; 24881ad6265SDimitry Andric 24981ad6265SDimitry Andric // Flags split: "f1" "f2" ... 25081ad6265SDimitry Andric SmallVector<StringRef, 6> SectionFlags; 25181ad6265SDimitry Andric Section2Flags.second.split(SectionFlags, ','); 25281ad6265SDimitry Andric Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags); 25381ad6265SDimitry Andric if (!ParsedFlagSet) 25481ad6265SDimitry Andric return ParsedFlagSet.takeError(); 25581ad6265SDimitry Andric SFU.NewFlags = *ParsedFlagSet; 25681ad6265SDimitry Andric 25781ad6265SDimitry Andric return SFU; 25881ad6265SDimitry Andric } 25981ad6265SDimitry Andric 260*0fca6ea1SDimitry Andric static Expected<uint8_t> parseVisibilityType(StringRef VisType) { 261*0fca6ea1SDimitry Andric const uint8_t Invalid = 0xff; 262*0fca6ea1SDimitry Andric uint8_t type = StringSwitch<uint8_t>(VisType) 263*0fca6ea1SDimitry Andric .Case("default", ELF::STV_DEFAULT) 264*0fca6ea1SDimitry Andric .Case("hidden", ELF::STV_HIDDEN) 265*0fca6ea1SDimitry Andric .Case("internal", ELF::STV_INTERNAL) 266*0fca6ea1SDimitry Andric .Case("protected", ELF::STV_PROTECTED) 267*0fca6ea1SDimitry Andric .Default(Invalid); 268*0fca6ea1SDimitry Andric if (type == Invalid) 269*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 270*0fca6ea1SDimitry Andric "'%s' is not a valid symbol visibility", 271*0fca6ea1SDimitry Andric VisType.str().c_str()); 272*0fca6ea1SDimitry Andric return type; 273*0fca6ea1SDimitry Andric } 274*0fca6ea1SDimitry Andric 27581ad6265SDimitry Andric namespace { 27681ad6265SDimitry Andric struct TargetInfo { 27781ad6265SDimitry Andric FileFormat Format; 27881ad6265SDimitry Andric MachineInfo Machine; 27981ad6265SDimitry Andric }; 28081ad6265SDimitry Andric } // namespace 28181ad6265SDimitry Andric 28281ad6265SDimitry Andric // FIXME: consolidate with the bfd parsing used by lld. 28381ad6265SDimitry Andric static const StringMap<MachineInfo> TargetMap{ 28481ad6265SDimitry Andric // Name, {EMachine, 64bit, LittleEndian} 28581ad6265SDimitry Andric // x86 28681ad6265SDimitry Andric {"elf32-i386", {ELF::EM_386, false, true}}, 28781ad6265SDimitry Andric {"elf32-x86-64", {ELF::EM_X86_64, false, true}}, 28881ad6265SDimitry Andric {"elf64-x86-64", {ELF::EM_X86_64, true, true}}, 28981ad6265SDimitry Andric // Intel MCU 29081ad6265SDimitry Andric {"elf32-iamcu", {ELF::EM_IAMCU, false, true}}, 29181ad6265SDimitry Andric // ARM 29281ad6265SDimitry Andric {"elf32-littlearm", {ELF::EM_ARM, false, true}}, 29381ad6265SDimitry Andric // ARM AArch64 29481ad6265SDimitry Andric {"elf64-aarch64", {ELF::EM_AARCH64, true, true}}, 29581ad6265SDimitry Andric {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}}, 29681ad6265SDimitry Andric // RISC-V 29781ad6265SDimitry Andric {"elf32-littleriscv", {ELF::EM_RISCV, false, true}}, 29881ad6265SDimitry Andric {"elf64-littleriscv", {ELF::EM_RISCV, true, true}}, 29981ad6265SDimitry Andric // PowerPC 30081ad6265SDimitry Andric {"elf32-powerpc", {ELF::EM_PPC, false, false}}, 30181ad6265SDimitry Andric {"elf32-powerpcle", {ELF::EM_PPC, false, true}}, 30281ad6265SDimitry Andric {"elf64-powerpc", {ELF::EM_PPC64, true, false}}, 30381ad6265SDimitry Andric {"elf64-powerpcle", {ELF::EM_PPC64, true, true}}, 30481ad6265SDimitry Andric // MIPS 30581ad6265SDimitry Andric {"elf32-bigmips", {ELF::EM_MIPS, false, false}}, 30681ad6265SDimitry Andric {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}}, 30781ad6265SDimitry Andric {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}}, 30881ad6265SDimitry Andric {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}}, 30981ad6265SDimitry Andric {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}}, 31081ad6265SDimitry Andric {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}}, 31181ad6265SDimitry Andric {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}}, 31281ad6265SDimitry Andric // SPARC 31381ad6265SDimitry Andric {"elf32-sparc", {ELF::EM_SPARC, false, false}}, 31481ad6265SDimitry Andric {"elf32-sparcel", {ELF::EM_SPARC, false, true}}, 31506c3fb27SDimitry Andric // Hexagon 31681ad6265SDimitry Andric {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}}, 31706c3fb27SDimitry Andric // LoongArch 31806c3fb27SDimitry Andric {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}}, 31906c3fb27SDimitry Andric {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}}, 32056727255SDimitry Andric // SystemZ 32156727255SDimitry Andric {"elf64-s390", {ELF::EM_S390, true, false}}, 32281ad6265SDimitry Andric }; 32381ad6265SDimitry Andric 32481ad6265SDimitry Andric static Expected<TargetInfo> 32581ad6265SDimitry Andric getOutputTargetInfoByTargetName(StringRef TargetName) { 32681ad6265SDimitry Andric StringRef OriginalTargetName = TargetName; 32781ad6265SDimitry Andric bool IsFreeBSD = TargetName.consume_back("-freebsd"); 32881ad6265SDimitry Andric auto Iter = TargetMap.find(TargetName); 32981ad6265SDimitry Andric if (Iter == std::end(TargetMap)) 33081ad6265SDimitry Andric return createStringError(errc::invalid_argument, 33181ad6265SDimitry Andric "invalid output format: '%s'", 33281ad6265SDimitry Andric OriginalTargetName.str().c_str()); 33381ad6265SDimitry Andric MachineInfo MI = Iter->getValue(); 33481ad6265SDimitry Andric if (IsFreeBSD) 33581ad6265SDimitry Andric MI.OSABI = ELF::ELFOSABI_FREEBSD; 33681ad6265SDimitry Andric 33781ad6265SDimitry Andric FileFormat Format; 3385f757f3fSDimitry Andric if (TargetName.starts_with("elf")) 33981ad6265SDimitry Andric Format = FileFormat::ELF; 34081ad6265SDimitry Andric else 34181ad6265SDimitry Andric // This should never happen because `TargetName` is valid (it certainly 34281ad6265SDimitry Andric // exists in the TargetMap). 34381ad6265SDimitry Andric llvm_unreachable("unknown target prefix"); 34481ad6265SDimitry Andric 34581ad6265SDimitry Andric return {TargetInfo{Format, MI}}; 34681ad6265SDimitry Andric } 34781ad6265SDimitry Andric 34881ad6265SDimitry Andric static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc, 34981ad6265SDimitry Andric StringRef Filename, MatchStyle MS, 35081ad6265SDimitry Andric function_ref<Error(Error)> ErrorCallback) { 35181ad6265SDimitry Andric StringSaver Saver(Alloc); 35281ad6265SDimitry Andric SmallVector<StringRef, 16> Lines; 35381ad6265SDimitry Andric auto BufOrErr = MemoryBuffer::getFile(Filename); 35481ad6265SDimitry Andric if (!BufOrErr) 35581ad6265SDimitry Andric return createFileError(Filename, BufOrErr.getError()); 35681ad6265SDimitry Andric 35781ad6265SDimitry Andric BufOrErr.get()->getBuffer().split(Lines, '\n'); 35881ad6265SDimitry Andric for (StringRef Line : Lines) { 35981ad6265SDimitry Andric // Ignore everything after '#', trim whitespace, and only add the symbol if 36081ad6265SDimitry Andric // it's not empty. 36181ad6265SDimitry Andric auto TrimmedLine = Line.split('#').first.trim(); 36281ad6265SDimitry Andric if (!TrimmedLine.empty()) 36381ad6265SDimitry Andric if (Error E = Symbols.addMatcher(NameOrPattern::create( 36481ad6265SDimitry Andric Saver.save(TrimmedLine), MS, ErrorCallback))) 36581ad6265SDimitry Andric return E; 36681ad6265SDimitry Andric } 36781ad6265SDimitry Andric 36881ad6265SDimitry Andric return Error::success(); 36981ad6265SDimitry Andric } 37081ad6265SDimitry Andric 37181ad6265SDimitry Andric static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename, 37281ad6265SDimitry Andric BumpPtrAllocator &Alloc, 37381ad6265SDimitry Andric StringRef Filename) { 37481ad6265SDimitry Andric StringSaver Saver(Alloc); 37581ad6265SDimitry Andric SmallVector<StringRef, 16> Lines; 37681ad6265SDimitry Andric auto BufOrErr = MemoryBuffer::getFile(Filename); 37781ad6265SDimitry Andric if (!BufOrErr) 37881ad6265SDimitry Andric return createFileError(Filename, BufOrErr.getError()); 37981ad6265SDimitry Andric 38081ad6265SDimitry Andric BufOrErr.get()->getBuffer().split(Lines, '\n'); 38181ad6265SDimitry Andric size_t NumLines = Lines.size(); 38281ad6265SDimitry Andric for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) { 38381ad6265SDimitry Andric StringRef TrimmedLine = Lines[LineNo].split('#').first.trim(); 38481ad6265SDimitry Andric if (TrimmedLine.empty()) 38581ad6265SDimitry Andric continue; 38681ad6265SDimitry Andric 38781ad6265SDimitry Andric std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' '); 38881ad6265SDimitry Andric StringRef NewName = Pair.second.trim(); 38981ad6265SDimitry Andric if (NewName.empty()) 39081ad6265SDimitry Andric return createStringError(errc::invalid_argument, 39181ad6265SDimitry Andric "%s:%zu: missing new symbol name", 39281ad6265SDimitry Andric Filename.str().c_str(), LineNo + 1); 39381ad6265SDimitry Andric SymbolsToRename.insert({Pair.first, NewName}); 39481ad6265SDimitry Andric } 39581ad6265SDimitry Andric return Error::success(); 39681ad6265SDimitry Andric } 39781ad6265SDimitry Andric 39881ad6265SDimitry Andric template <class T> static ErrorOr<T> getAsInteger(StringRef Val) { 39981ad6265SDimitry Andric T Result; 40081ad6265SDimitry Andric if (Val.getAsInteger(0, Result)) 40181ad6265SDimitry Andric return errc::invalid_argument; 40281ad6265SDimitry Andric return Result; 40381ad6265SDimitry Andric } 40481ad6265SDimitry Andric 40581ad6265SDimitry Andric namespace { 40681ad6265SDimitry Andric 40781ad6265SDimitry Andric enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip }; 40881ad6265SDimitry Andric 40981ad6265SDimitry Andric } // anonymous namespace 41081ad6265SDimitry Andric 41181ad6265SDimitry Andric static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS, 41281ad6265SDimitry Andric ToolType Tool) { 41381ad6265SDimitry Andric StringRef HelpText, ToolName; 41481ad6265SDimitry Andric switch (Tool) { 41581ad6265SDimitry Andric case ToolType::Objcopy: 41681ad6265SDimitry Andric ToolName = "llvm-objcopy"; 41781ad6265SDimitry Andric HelpText = " [options] input [output]"; 41881ad6265SDimitry Andric break; 41981ad6265SDimitry Andric case ToolType::Strip: 42081ad6265SDimitry Andric ToolName = "llvm-strip"; 42181ad6265SDimitry Andric HelpText = " [options] inputs..."; 42281ad6265SDimitry Andric break; 42381ad6265SDimitry Andric case ToolType::InstallNameTool: 42481ad6265SDimitry Andric ToolName = "llvm-install-name-tool"; 42581ad6265SDimitry Andric HelpText = " [options] input"; 42681ad6265SDimitry Andric break; 42781ad6265SDimitry Andric case ToolType::BitcodeStrip: 42881ad6265SDimitry Andric ToolName = "llvm-bitcode-strip"; 42981ad6265SDimitry Andric HelpText = " [options] input"; 43081ad6265SDimitry Andric break; 43181ad6265SDimitry Andric } 43281ad6265SDimitry Andric OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(), 43381ad6265SDimitry Andric (ToolName + " tool").str().c_str()); 43481ad6265SDimitry Andric // TODO: Replace this with libOption call once it adds extrahelp support. 43581ad6265SDimitry Andric // The CommandLine library has a cl::extrahelp class to support this, 43681ad6265SDimitry Andric // but libOption does not have that yet. 43781ad6265SDimitry Andric OS << "\nPass @FILE as argument to read options from FILE.\n"; 43881ad6265SDimitry Andric } 43981ad6265SDimitry Andric 44081ad6265SDimitry Andric static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) { 44181ad6265SDimitry Andric // Parse value given with --add-symbol option and create the 44281ad6265SDimitry Andric // new symbol if possible. The value format for --add-symbol is: 44381ad6265SDimitry Andric // 44481ad6265SDimitry Andric // <name>=[<section>:]<value>[,<flags>] 44581ad6265SDimitry Andric // 44681ad6265SDimitry Andric // where: 44781ad6265SDimitry Andric // <name> - symbol name, can be empty string 44881ad6265SDimitry Andric // <section> - optional section name. If not given ABS symbol is created 44981ad6265SDimitry Andric // <value> - symbol value, can be decimal or hexadecimal number prefixed 45081ad6265SDimitry Andric // with 0x. 45181ad6265SDimitry Andric // <flags> - optional flags affecting symbol type, binding or visibility. 45281ad6265SDimitry Andric NewSymbolInfo SI; 45381ad6265SDimitry Andric StringRef Value; 45481ad6265SDimitry Andric std::tie(SI.SymbolName, Value) = FlagValue.split('='); 45581ad6265SDimitry Andric if (Value.empty()) 45681ad6265SDimitry Andric return createStringError( 45781ad6265SDimitry Andric errc::invalid_argument, 45881ad6265SDimitry Andric "bad format for --add-symbol, missing '=' after '%s'", 45981ad6265SDimitry Andric SI.SymbolName.str().c_str()); 46081ad6265SDimitry Andric 46181ad6265SDimitry Andric if (Value.contains(':')) { 46281ad6265SDimitry Andric std::tie(SI.SectionName, Value) = Value.split(':'); 46381ad6265SDimitry Andric if (SI.SectionName.empty() || Value.empty()) 46481ad6265SDimitry Andric return createStringError( 46581ad6265SDimitry Andric errc::invalid_argument, 46681ad6265SDimitry Andric "bad format for --add-symbol, missing section name or symbol value"); 46781ad6265SDimitry Andric } 46881ad6265SDimitry Andric 46981ad6265SDimitry Andric SmallVector<StringRef, 6> Flags; 47081ad6265SDimitry Andric Value.split(Flags, ','); 47181ad6265SDimitry Andric if (Flags[0].getAsInteger(0, SI.Value)) 47281ad6265SDimitry Andric return createStringError(errc::invalid_argument, "bad symbol value: '%s'", 47381ad6265SDimitry Andric Flags[0].str().c_str()); 47481ad6265SDimitry Andric 47581ad6265SDimitry Andric using Functor = std::function<void()>; 47681ad6265SDimitry Andric SmallVector<StringRef, 6> UnsupportedFlags; 47781ad6265SDimitry Andric for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I) 47881ad6265SDimitry Andric static_cast<Functor>( 47981ad6265SDimitry Andric StringSwitch<Functor>(Flags[I]) 48081ad6265SDimitry Andric .CaseLower("global", 48181ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Global); }) 48281ad6265SDimitry Andric .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); }) 48381ad6265SDimitry Andric .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); }) 48481ad6265SDimitry Andric .CaseLower("default", 48581ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Default); }) 48681ad6265SDimitry Andric .CaseLower("hidden", 48781ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Hidden); }) 48881ad6265SDimitry Andric .CaseLower("protected", 48981ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Protected); }) 49081ad6265SDimitry Andric .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); }) 49181ad6265SDimitry Andric .CaseLower("section", 49281ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Section); }) 49381ad6265SDimitry Andric .CaseLower("object", 49481ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Object); }) 49581ad6265SDimitry Andric .CaseLower("function", 49681ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Function); }) 49781ad6265SDimitry Andric .CaseLower( 49881ad6265SDimitry Andric "indirect-function", 49981ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); }) 50081ad6265SDimitry Andric .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); }) 50181ad6265SDimitry Andric .CaseLower("constructor", 50281ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Constructor); }) 50381ad6265SDimitry Andric .CaseLower("warning", 50481ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Warning); }) 50581ad6265SDimitry Andric .CaseLower("indirect", 50681ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Indirect); }) 50781ad6265SDimitry Andric .CaseLower("synthetic", 50881ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::Synthetic); }) 50981ad6265SDimitry Andric .CaseLower("unique-object", 51081ad6265SDimitry Andric [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); }) 51181ad6265SDimitry Andric .StartsWithLower("before=", 51281ad6265SDimitry Andric [&] { 51381ad6265SDimitry Andric StringRef SymNamePart = 51481ad6265SDimitry Andric Flags[I].split('=').second; 51581ad6265SDimitry Andric 51681ad6265SDimitry Andric if (!SymNamePart.empty()) 51781ad6265SDimitry Andric SI.BeforeSyms.push_back(SymNamePart); 51881ad6265SDimitry Andric }) 51981ad6265SDimitry Andric .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))(); 52081ad6265SDimitry Andric if (!UnsupportedFlags.empty()) 52181ad6265SDimitry Andric return createStringError(errc::invalid_argument, 52281ad6265SDimitry Andric "unsupported flag%s for --add-symbol: '%s'", 52381ad6265SDimitry Andric UnsupportedFlags.size() > 1 ? "s" : "", 52481ad6265SDimitry Andric join(UnsupportedFlags, "', '").c_str()); 52581ad6265SDimitry Andric 52681ad6265SDimitry Andric return SI; 52781ad6265SDimitry Andric } 52881ad6265SDimitry Andric 52981ad6265SDimitry Andric // Parse input option \p ArgValue and load section data. This function 53081ad6265SDimitry Andric // extracts section name and name of the file keeping section data from 53181ad6265SDimitry Andric // ArgValue, loads data from the file, and stores section name and data 53281ad6265SDimitry Andric // into the vector of new sections \p NewSections. 53381ad6265SDimitry Andric static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName, 534*0fca6ea1SDimitry Andric SmallVector<NewSectionInfo, 0> &NewSections) { 53581ad6265SDimitry Andric if (!ArgValue.contains('=')) 53681ad6265SDimitry Andric return createStringError(errc::invalid_argument, 53781ad6265SDimitry Andric "bad format for " + OptionName + ": missing '='"); 53881ad6265SDimitry Andric 53981ad6265SDimitry Andric std::pair<StringRef, StringRef> SecPair = ArgValue.split("="); 54081ad6265SDimitry Andric if (SecPair.second.empty()) 54181ad6265SDimitry Andric return createStringError(errc::invalid_argument, "bad format for " + 54281ad6265SDimitry Andric OptionName + 54381ad6265SDimitry Andric ": missing file name"); 54481ad6265SDimitry Andric 54581ad6265SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 54681ad6265SDimitry Andric MemoryBuffer::getFile(SecPair.second); 54781ad6265SDimitry Andric if (!BufOrErr) 54881ad6265SDimitry Andric return createFileError(SecPair.second, 54981ad6265SDimitry Andric errorCodeToError(BufOrErr.getError())); 55081ad6265SDimitry Andric 55181ad6265SDimitry Andric NewSections.push_back({SecPair.first, std::move(*BufOrErr)}); 55281ad6265SDimitry Andric return Error::success(); 55381ad6265SDimitry Andric } 55481ad6265SDimitry Andric 555*0fca6ea1SDimitry Andric static Expected<int64_t> parseChangeSectionLMA(StringRef ArgValue, 556*0fca6ea1SDimitry Andric StringRef OptionName) { 557*0fca6ea1SDimitry Andric StringRef StringValue; 558*0fca6ea1SDimitry Andric if (ArgValue.starts_with("*+")) { 559*0fca6ea1SDimitry Andric StringValue = ArgValue.slice(2, StringRef::npos); 560*0fca6ea1SDimitry Andric } else if (ArgValue.starts_with("*-")) { 561*0fca6ea1SDimitry Andric StringValue = ArgValue.slice(1, StringRef::npos); 562*0fca6ea1SDimitry Andric } else if (ArgValue.contains("=")) { 563*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 564*0fca6ea1SDimitry Andric "bad format for " + OptionName + 565*0fca6ea1SDimitry Andric ": changing LMA to a specific value is not " 566*0fca6ea1SDimitry Andric "supported. Use *+val or *-val instead"); 567*0fca6ea1SDimitry Andric } else if (ArgValue.contains("+") || ArgValue.contains("-")) { 568*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 569*0fca6ea1SDimitry Andric "bad format for " + OptionName + 570*0fca6ea1SDimitry Andric ": changing a specific section LMA is not " 571*0fca6ea1SDimitry Andric "supported. Use *+val or *-val instead"); 572*0fca6ea1SDimitry Andric } 573*0fca6ea1SDimitry Andric if (StringValue.empty()) 574*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 575*0fca6ea1SDimitry Andric "bad format for " + OptionName + 576*0fca6ea1SDimitry Andric ": missing LMA offset"); 577*0fca6ea1SDimitry Andric 578*0fca6ea1SDimitry Andric auto LMAValue = getAsInteger<int64_t>(StringValue); 579*0fca6ea1SDimitry Andric if (!LMAValue) 580*0fca6ea1SDimitry Andric return createStringError(LMAValue.getError(), 581*0fca6ea1SDimitry Andric "bad format for " + OptionName + ": value after " + 582*0fca6ea1SDimitry Andric ArgValue.slice(0, 2) + " is " + StringValue + 583*0fca6ea1SDimitry Andric " when it should be an integer"); 584*0fca6ea1SDimitry Andric return *LMAValue; 585*0fca6ea1SDimitry Andric } 586*0fca6ea1SDimitry Andric 58781ad6265SDimitry Andric // parseObjcopyOptions returns the config and sets the input arguments. If a 58881ad6265SDimitry Andric // help flag is set then parseObjcopyOptions will print the help messege and 58981ad6265SDimitry Andric // exit. 59081ad6265SDimitry Andric Expected<DriverConfig> 59181ad6265SDimitry Andric objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr, 59281ad6265SDimitry Andric function_ref<Error(Error)> ErrorCallback) { 59381ad6265SDimitry Andric DriverConfig DC; 59481ad6265SDimitry Andric ObjcopyOptTable T; 59581ad6265SDimitry Andric 59681ad6265SDimitry Andric const char *const *DashDash = 597bdd1243dSDimitry Andric llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; }); 598bdd1243dSDimitry Andric ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash); 59981ad6265SDimitry Andric if (DashDash != RawArgsArr.end()) 60081ad6265SDimitry Andric DashDash = std::next(DashDash); 60181ad6265SDimitry Andric 60281ad6265SDimitry Andric unsigned MissingArgumentIndex, MissingArgumentCount; 60381ad6265SDimitry Andric llvm::opt::InputArgList InputArgs = 60481ad6265SDimitry Andric T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 60581ad6265SDimitry Andric 606*0fca6ea1SDimitry Andric if (MissingArgumentCount) 607*0fca6ea1SDimitry Andric return createStringError( 608*0fca6ea1SDimitry Andric errc::invalid_argument, 609*0fca6ea1SDimitry Andric "argument to '%s' is missing (expected %d value(s))", 610*0fca6ea1SDimitry Andric InputArgs.getArgString(MissingArgumentIndex), MissingArgumentCount); 611*0fca6ea1SDimitry Andric 61281ad6265SDimitry Andric if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) { 61381ad6265SDimitry Andric printHelp(T, errs(), ToolType::Objcopy); 61481ad6265SDimitry Andric exit(1); 61581ad6265SDimitry Andric } 61681ad6265SDimitry Andric 61781ad6265SDimitry Andric if (InputArgs.hasArg(OBJCOPY_help)) { 61881ad6265SDimitry Andric printHelp(T, outs(), ToolType::Objcopy); 61981ad6265SDimitry Andric exit(0); 62081ad6265SDimitry Andric } 62181ad6265SDimitry Andric 62281ad6265SDimitry Andric if (InputArgs.hasArg(OBJCOPY_version)) { 62381ad6265SDimitry Andric outs() << "llvm-objcopy, compatible with GNU objcopy\n"; 62481ad6265SDimitry Andric cl::PrintVersionMessage(); 62581ad6265SDimitry Andric exit(0); 62681ad6265SDimitry Andric } 62781ad6265SDimitry Andric 62881ad6265SDimitry Andric SmallVector<const char *, 2> Positional; 62981ad6265SDimitry Andric 630bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN)) 63181ad6265SDimitry Andric return createStringError(errc::invalid_argument, "unknown argument '%s'", 63281ad6265SDimitry Andric Arg->getAsString(InputArgs).c_str()); 63381ad6265SDimitry Andric 634bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT)) 63581ad6265SDimitry Andric Positional.push_back(Arg->getValue()); 63681ad6265SDimitry Andric std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional)); 63781ad6265SDimitry Andric 63881ad6265SDimitry Andric if (Positional.empty()) 63981ad6265SDimitry Andric return createStringError(errc::invalid_argument, "no input file specified"); 64081ad6265SDimitry Andric 64181ad6265SDimitry Andric if (Positional.size() > 2) 64281ad6265SDimitry Andric return createStringError(errc::invalid_argument, 64381ad6265SDimitry Andric "too many positional arguments"); 64481ad6265SDimitry Andric 64581ad6265SDimitry Andric ConfigManager ConfigMgr; 64681ad6265SDimitry Andric CommonConfig &Config = ConfigMgr.Common; 64781ad6265SDimitry Andric COFFConfig &COFFConfig = ConfigMgr.COFF; 64881ad6265SDimitry Andric ELFConfig &ELFConfig = ConfigMgr.ELF; 64981ad6265SDimitry Andric MachOConfig &MachOConfig = ConfigMgr.MachO; 65081ad6265SDimitry Andric Config.InputFilename = Positional[0]; 65181ad6265SDimitry Andric Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1]; 65281ad6265SDimitry Andric if (InputArgs.hasArg(OBJCOPY_target) && 65381ad6265SDimitry Andric (InputArgs.hasArg(OBJCOPY_input_target) || 65481ad6265SDimitry Andric InputArgs.hasArg(OBJCOPY_output_target))) 65581ad6265SDimitry Andric return createStringError( 65681ad6265SDimitry Andric errc::invalid_argument, 65781ad6265SDimitry Andric "--target cannot be used with --input-target or --output-target"); 65881ad6265SDimitry Andric 65981ad6265SDimitry Andric if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard)) 66081ad6265SDimitry Andric return createStringError(errc::invalid_argument, 66181ad6265SDimitry Andric "--regex and --wildcard are incompatible"); 66281ad6265SDimitry Andric 66381ad6265SDimitry Andric MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex) 66481ad6265SDimitry Andric ? MatchStyle::Regex 66581ad6265SDimitry Andric : MatchStyle::Wildcard; 66681ad6265SDimitry Andric MatchStyle SymbolMatchStyle 66781ad6265SDimitry Andric = InputArgs.hasArg(OBJCOPY_regex) ? MatchStyle::Regex 66881ad6265SDimitry Andric : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard 66981ad6265SDimitry Andric : MatchStyle::Literal; 67081ad6265SDimitry Andric StringRef InputFormat, OutputFormat; 67181ad6265SDimitry Andric if (InputArgs.hasArg(OBJCOPY_target)) { 67281ad6265SDimitry Andric InputFormat = InputArgs.getLastArgValue(OBJCOPY_target); 67381ad6265SDimitry Andric OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target); 67481ad6265SDimitry Andric } else { 67581ad6265SDimitry Andric InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target); 67681ad6265SDimitry Andric OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target); 67781ad6265SDimitry Andric } 67881ad6265SDimitry Andric 67981ad6265SDimitry Andric // FIXME: Currently, we ignore the target for non-binary/ihex formats 68081ad6265SDimitry Andric // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the 68181ad6265SDimitry Andric // format by llvm::object::createBinary regardless of the option value. 68281ad6265SDimitry Andric Config.InputFormat = StringSwitch<FileFormat>(InputFormat) 68381ad6265SDimitry Andric .Case("binary", FileFormat::Binary) 68481ad6265SDimitry Andric .Case("ihex", FileFormat::IHex) 68581ad6265SDimitry Andric .Default(FileFormat::Unspecified); 68681ad6265SDimitry Andric 68781ad6265SDimitry Andric if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) { 68881ad6265SDimitry Andric const uint8_t Invalid = 0xff; 68981ad6265SDimitry Andric StringRef VisibilityStr = 69081ad6265SDimitry Andric InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility); 69181ad6265SDimitry Andric 69281ad6265SDimitry Andric ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr) 69381ad6265SDimitry Andric .Case("default", ELF::STV_DEFAULT) 69481ad6265SDimitry Andric .Case("hidden", ELF::STV_HIDDEN) 69581ad6265SDimitry Andric .Case("internal", ELF::STV_INTERNAL) 69681ad6265SDimitry Andric .Case("protected", ELF::STV_PROTECTED) 69781ad6265SDimitry Andric .Default(Invalid); 69881ad6265SDimitry Andric 69981ad6265SDimitry Andric if (ELFConfig.NewSymbolVisibility == Invalid) 70081ad6265SDimitry Andric return createStringError(errc::invalid_argument, 70181ad6265SDimitry Andric "'%s' is not a valid symbol visibility", 70281ad6265SDimitry Andric VisibilityStr.str().c_str()); 70381ad6265SDimitry Andric } 70481ad6265SDimitry Andric 70581ad6265SDimitry Andric for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) { 70681ad6265SDimitry Andric StringRef Subsystem, Version; 70781ad6265SDimitry Andric std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':'); 70881ad6265SDimitry Andric COFFConfig.Subsystem = 70981ad6265SDimitry Andric StringSwitch<unsigned>(Subsystem.lower()) 71081ad6265SDimitry Andric .Case("boot_application", 71181ad6265SDimitry Andric COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) 71281ad6265SDimitry Andric .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI) 713*0fca6ea1SDimitry Andric .Cases("efi_application", "efi-app", 714*0fca6ea1SDimitry Andric COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION) 715*0fca6ea1SDimitry Andric .Cases("efi_boot_service_driver", "efi-bsd", 71681ad6265SDimitry Andric COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) 71781ad6265SDimitry Andric .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM) 718*0fca6ea1SDimitry Andric .Cases("efi_runtime_driver", "efi-rtd", 71981ad6265SDimitry Andric COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) 72081ad6265SDimitry Andric .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE) 72181ad6265SDimitry Andric .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI) 72281ad6265SDimitry Andric .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI) 72381ad6265SDimitry Andric .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN); 72481ad6265SDimitry Andric if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN) 72581ad6265SDimitry Andric return createStringError(errc::invalid_argument, 72681ad6265SDimitry Andric "'%s' is not a valid subsystem", 72781ad6265SDimitry Andric Subsystem.str().c_str()); 72881ad6265SDimitry Andric if (!Version.empty()) { 72981ad6265SDimitry Andric StringRef Major, Minor; 73081ad6265SDimitry Andric std::tie(Major, Minor) = Version.split('.'); 73181ad6265SDimitry Andric unsigned Number; 73281ad6265SDimitry Andric if (Major.getAsInteger(10, Number)) 73381ad6265SDimitry Andric return createStringError(errc::invalid_argument, 73481ad6265SDimitry Andric "'%s' is not a valid subsystem major version", 73581ad6265SDimitry Andric Major.str().c_str()); 73681ad6265SDimitry Andric COFFConfig.MajorSubsystemVersion = Number; 73781ad6265SDimitry Andric Number = 0; 73881ad6265SDimitry Andric if (!Minor.empty() && Minor.getAsInteger(10, Number)) 73981ad6265SDimitry Andric return createStringError(errc::invalid_argument, 74081ad6265SDimitry Andric "'%s' is not a valid subsystem minor version", 74181ad6265SDimitry Andric Minor.str().c_str()); 74281ad6265SDimitry Andric COFFConfig.MinorSubsystemVersion = Number; 74381ad6265SDimitry Andric } 74481ad6265SDimitry Andric } 74581ad6265SDimitry Andric 74681ad6265SDimitry Andric Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat) 74781ad6265SDimitry Andric .Case("binary", FileFormat::Binary) 74881ad6265SDimitry Andric .Case("ihex", FileFormat::IHex) 749*0fca6ea1SDimitry Andric .Case("srec", FileFormat::SREC) 75081ad6265SDimitry Andric .Default(FileFormat::Unspecified); 75181ad6265SDimitry Andric if (Config.OutputFormat == FileFormat::Unspecified) { 75281ad6265SDimitry Andric if (OutputFormat.empty()) { 75381ad6265SDimitry Andric Config.OutputFormat = Config.InputFormat; 75481ad6265SDimitry Andric } else { 75581ad6265SDimitry Andric Expected<TargetInfo> Target = 75681ad6265SDimitry Andric getOutputTargetInfoByTargetName(OutputFormat); 75781ad6265SDimitry Andric if (!Target) 75881ad6265SDimitry Andric return Target.takeError(); 75981ad6265SDimitry Andric Config.OutputFormat = Target->Format; 76081ad6265SDimitry Andric Config.OutputArch = Target->Machine; 76181ad6265SDimitry Andric } 76281ad6265SDimitry Andric } 76381ad6265SDimitry Andric 764972a253aSDimitry Andric if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) { 765972a253aSDimitry Andric Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue()) 766bdd1243dSDimitry Andric .Case("zlib", DebugCompressionType::Zlib) 767bdd1243dSDimitry Andric .Case("zstd", DebugCompressionType::Zstd) 76881ad6265SDimitry Andric .Default(DebugCompressionType::None); 769bdd1243dSDimitry Andric if (Config.CompressionType == DebugCompressionType::None) { 77081ad6265SDimitry Andric return createStringError( 77181ad6265SDimitry Andric errc::invalid_argument, 77281ad6265SDimitry Andric "invalid or unsupported --compress-debug-sections format: %s", 773972a253aSDimitry Andric A->getValue()); 774bdd1243dSDimitry Andric } 775bdd1243dSDimitry Andric if (const char *Reason = compression::getReasonIfUnsupported( 776bdd1243dSDimitry Andric compression::formatFor(Config.CompressionType))) 777bdd1243dSDimitry Andric return createStringError(errc::invalid_argument, Reason); 77881ad6265SDimitry Andric } 77981ad6265SDimitry Andric 780*0fca6ea1SDimitry Andric for (const auto *A : InputArgs.filtered(OBJCOPY_compress_sections)) { 781*0fca6ea1SDimitry Andric SmallVector<StringRef, 0> Fields; 782*0fca6ea1SDimitry Andric StringRef(A->getValue()).split(Fields, '='); 783*0fca6ea1SDimitry Andric if (Fields.size() != 2 || Fields[1].empty()) { 784*0fca6ea1SDimitry Andric return createStringError( 785*0fca6ea1SDimitry Andric errc::invalid_argument, 786*0fca6ea1SDimitry Andric A->getSpelling() + 787*0fca6ea1SDimitry Andric ": parse error, not 'section-glob=[none|zlib|zstd]'"); 788*0fca6ea1SDimitry Andric } 789*0fca6ea1SDimitry Andric 790*0fca6ea1SDimitry Andric auto Type = StringSwitch<DebugCompressionType>(Fields[1]) 791*0fca6ea1SDimitry Andric .Case("zlib", DebugCompressionType::Zlib) 792*0fca6ea1SDimitry Andric .Case("zstd", DebugCompressionType::Zstd) 793*0fca6ea1SDimitry Andric .Default(DebugCompressionType::None); 794*0fca6ea1SDimitry Andric if (Type == DebugCompressionType::None && Fields[1] != "none") { 795*0fca6ea1SDimitry Andric return createStringError( 796*0fca6ea1SDimitry Andric errc::invalid_argument, 797*0fca6ea1SDimitry Andric "invalid or unsupported --compress-sections format: %s", 798*0fca6ea1SDimitry Andric A->getValue()); 799*0fca6ea1SDimitry Andric } 800*0fca6ea1SDimitry Andric 801*0fca6ea1SDimitry Andric auto &P = Config.compressSections.emplace_back(); 802*0fca6ea1SDimitry Andric P.second = Type; 803*0fca6ea1SDimitry Andric auto Matcher = 804*0fca6ea1SDimitry Andric NameOrPattern::create(Fields[0], SectionMatchStyle, ErrorCallback); 805*0fca6ea1SDimitry Andric // =none allows overriding a previous =zlib or =zstd. Reject negative 806*0fca6ea1SDimitry Andric // patterns, which would be confusing. 807*0fca6ea1SDimitry Andric if (Matcher && !Matcher->isPositiveMatch()) { 808*0fca6ea1SDimitry Andric return createStringError( 809*0fca6ea1SDimitry Andric errc::invalid_argument, 810*0fca6ea1SDimitry Andric "--compress-sections: negative pattern is unsupported"); 811*0fca6ea1SDimitry Andric } 812*0fca6ea1SDimitry Andric if (Error E = P.first.addMatcher(std::move(Matcher))) 813*0fca6ea1SDimitry Andric return std::move(E); 814*0fca6ea1SDimitry Andric } 815*0fca6ea1SDimitry Andric 81681ad6265SDimitry Andric Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); 81781ad6265SDimitry Andric // The gnu_debuglink's target is expected to not change or else its CRC would 81881ad6265SDimitry Andric // become invalidated and get rejected. We can avoid recalculating the 81981ad6265SDimitry Andric // checksum for every target file inside an archive by precomputing the CRC 82081ad6265SDimitry Andric // here. This prevents a significant amount of I/O. 82181ad6265SDimitry Andric if (!Config.AddGnuDebugLink.empty()) { 82281ad6265SDimitry Andric auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink); 82381ad6265SDimitry Andric if (!DebugOrErr) 82481ad6265SDimitry Andric return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError()); 82581ad6265SDimitry Andric auto Debug = std::move(*DebugOrErr); 82681ad6265SDimitry Andric Config.GnuDebugLinkCRC32 = 82781ad6265SDimitry Andric llvm::crc32(arrayRefFromStringRef(Debug->getBuffer())); 82881ad6265SDimitry Andric } 82981ad6265SDimitry Andric Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); 830*0fca6ea1SDimitry Andric 83181ad6265SDimitry Andric Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols); 832*0fca6ea1SDimitry Andric Config.SymbolsPrefixRemove = 833*0fca6ea1SDimitry Andric InputArgs.getLastArgValue(OBJCOPY_remove_symbol_prefix); 834*0fca6ea1SDimitry Andric 83581ad6265SDimitry Andric Config.AllocSectionsPrefix = 83681ad6265SDimitry Andric InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections); 83781ad6265SDimitry Andric if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition)) 83881ad6265SDimitry Andric Config.ExtractPartition = Arg->getValue(); 83981ad6265SDimitry Andric 8405f757f3fSDimitry Andric if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) { 8415f757f3fSDimitry Andric if (Config.OutputFormat != FileFormat::Binary) 8425f757f3fSDimitry Andric return createStringError( 8435f757f3fSDimitry Andric errc::invalid_argument, 8445f757f3fSDimitry Andric "'--gap-fill' is only supported for binary output"); 8455f757f3fSDimitry Andric ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue()); 8465f757f3fSDimitry Andric if (!Val) 8475f757f3fSDimitry Andric return createStringError(Val.getError(), "--gap-fill: bad number: %s", 8485f757f3fSDimitry Andric A->getValue()); 8495f757f3fSDimitry Andric uint8_t ByteVal = Val.get(); 8505f757f3fSDimitry Andric if (ByteVal != Val.get()) 8515f757f3fSDimitry Andric return createStringError(std::errc::value_too_large, 8525f757f3fSDimitry Andric "gap-fill value %s is out of range (0 to 0xff)", 8535f757f3fSDimitry Andric A->getValue()); 8545f757f3fSDimitry Andric Config.GapFill = ByteVal; 8555f757f3fSDimitry Andric } 8565f757f3fSDimitry Andric 8575f757f3fSDimitry Andric if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) { 8585f757f3fSDimitry Andric if (Config.OutputFormat != FileFormat::Binary) 8595f757f3fSDimitry Andric return createStringError( 8605f757f3fSDimitry Andric errc::invalid_argument, 8615f757f3fSDimitry Andric "'--pad-to' is only supported for binary output"); 8625f757f3fSDimitry Andric ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue()); 8635f757f3fSDimitry Andric if (!Addr) 8645f757f3fSDimitry Andric return createStringError(Addr.getError(), "--pad-to: bad number: %s", 8655f757f3fSDimitry Andric A->getValue()); 8665f757f3fSDimitry Andric Config.PadTo = *Addr; 8675f757f3fSDimitry Andric } 8685f757f3fSDimitry Andric 869*0fca6ea1SDimitry Andric if (const auto *Arg = InputArgs.getLastArg(OBJCOPY_change_section_lma)) { 870*0fca6ea1SDimitry Andric Expected<int64_t> LMAValue = 871*0fca6ea1SDimitry Andric parseChangeSectionLMA(Arg->getValue(), Arg->getSpelling()); 872*0fca6ea1SDimitry Andric if (!LMAValue) 873*0fca6ea1SDimitry Andric return LMAValue.takeError(); 874*0fca6ea1SDimitry Andric Config.ChangeSectionLMAValAll = *LMAValue; 875*0fca6ea1SDimitry Andric } 876*0fca6ea1SDimitry Andric 877bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) { 87881ad6265SDimitry Andric if (!StringRef(Arg->getValue()).contains('=')) 87981ad6265SDimitry Andric return createStringError(errc::invalid_argument, 88081ad6265SDimitry Andric "bad format for --redefine-sym"); 88181ad6265SDimitry Andric auto Old2New = StringRef(Arg->getValue()).split('='); 88281ad6265SDimitry Andric if (!Config.SymbolsToRename.insert(Old2New).second) 88381ad6265SDimitry Andric return createStringError(errc::invalid_argument, 88481ad6265SDimitry Andric "multiple redefinition of symbol '%s'", 88581ad6265SDimitry Andric Old2New.first.str().c_str()); 88681ad6265SDimitry Andric } 88781ad6265SDimitry Andric 888bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols)) 88981ad6265SDimitry Andric if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc, 89081ad6265SDimitry Andric Arg->getValue())) 89181ad6265SDimitry Andric return std::move(E); 89281ad6265SDimitry Andric 893bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) { 89481ad6265SDimitry Andric Expected<SectionRename> SR = 89581ad6265SDimitry Andric parseRenameSectionValue(StringRef(Arg->getValue())); 89681ad6265SDimitry Andric if (!SR) 89781ad6265SDimitry Andric return SR.takeError(); 89881ad6265SDimitry Andric if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second) 89981ad6265SDimitry Andric return createStringError(errc::invalid_argument, 90081ad6265SDimitry Andric "multiple renames of section '%s'", 90181ad6265SDimitry Andric SR->OriginalName.str().c_str()); 90281ad6265SDimitry Andric } 903bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) { 90481ad6265SDimitry Andric Expected<std::pair<StringRef, uint64_t>> NameAndAlign = 905753f127fSDimitry Andric parseSetSectionAttribute("--set-section-alignment", Arg->getValue()); 90681ad6265SDimitry Andric if (!NameAndAlign) 90781ad6265SDimitry Andric return NameAndAlign.takeError(); 90881ad6265SDimitry Andric Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second; 90981ad6265SDimitry Andric } 910bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) { 91181ad6265SDimitry Andric Expected<SectionFlagsUpdate> SFU = 91281ad6265SDimitry Andric parseSetSectionFlagValue(Arg->getValue()); 91381ad6265SDimitry Andric if (!SFU) 91481ad6265SDimitry Andric return SFU.takeError(); 91581ad6265SDimitry Andric if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second) 91681ad6265SDimitry Andric return createStringError( 91781ad6265SDimitry Andric errc::invalid_argument, 91881ad6265SDimitry Andric "--set-section-flags set multiple times for section '%s'", 91981ad6265SDimitry Andric SFU->Name.str().c_str()); 92081ad6265SDimitry Andric } 921bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) { 922753f127fSDimitry Andric Expected<std::pair<StringRef, uint64_t>> NameAndType = 923753f127fSDimitry Andric parseSetSectionAttribute("--set-section-type", Arg->getValue()); 924753f127fSDimitry Andric if (!NameAndType) 925753f127fSDimitry Andric return NameAndType.takeError(); 926753f127fSDimitry Andric Config.SetSectionType[NameAndType->first] = NameAndType->second; 927753f127fSDimitry Andric } 928753f127fSDimitry Andric // Prohibit combinations of --set-section-{flags,type} when the section name 929753f127fSDimitry Andric // is used as the destination of a --rename-section. 93081ad6265SDimitry Andric for (const auto &E : Config.SectionsToRename) { 93181ad6265SDimitry Andric const SectionRename &SR = E.second; 932753f127fSDimitry Andric auto Err = [&](const char *Option) { 93381ad6265SDimitry Andric return createStringError( 93481ad6265SDimitry Andric errc::invalid_argument, 935753f127fSDimitry Andric "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option, 93681ad6265SDimitry Andric SR.NewName.str().c_str(), SR.OriginalName.str().c_str(), 93781ad6265SDimitry Andric SR.NewName.str().c_str()); 938753f127fSDimitry Andric }; 939753f127fSDimitry Andric if (Config.SetSectionFlags.count(SR.NewName)) 940753f127fSDimitry Andric return Err("flags"); 941753f127fSDimitry Andric if (Config.SetSectionType.count(SR.NewName)) 942753f127fSDimitry Andric return Err("type"); 94381ad6265SDimitry Andric } 94481ad6265SDimitry Andric 945bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section)) 94681ad6265SDimitry Andric if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( 94781ad6265SDimitry Andric Arg->getValue(), SectionMatchStyle, ErrorCallback))) 94881ad6265SDimitry Andric return std::move(E); 949bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section)) 95081ad6265SDimitry Andric if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( 95181ad6265SDimitry Andric Arg->getValue(), SectionMatchStyle, ErrorCallback))) 95281ad6265SDimitry Andric return std::move(E); 953bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section)) 95481ad6265SDimitry Andric if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create( 95581ad6265SDimitry Andric Arg->getValue(), SectionMatchStyle, ErrorCallback))) 95681ad6265SDimitry Andric return std::move(E); 957bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) { 95881ad6265SDimitry Andric if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section", 95981ad6265SDimitry Andric Config.AddSection)) 96081ad6265SDimitry Andric return std::move(Err); 96181ad6265SDimitry Andric } 962bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) { 96381ad6265SDimitry Andric if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section", 96481ad6265SDimitry Andric Config.UpdateSection)) 96581ad6265SDimitry Andric return std::move(Err); 96681ad6265SDimitry Andric } 96781ad6265SDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) { 96881ad6265SDimitry Andric StringRef Value(Arg->getValue()); 96981ad6265SDimitry Andric if (Value.split('=').second.empty()) 97081ad6265SDimitry Andric return createStringError( 97181ad6265SDimitry Andric errc::invalid_argument, 97281ad6265SDimitry Andric "bad format for --dump-section, expected section=file"); 97381ad6265SDimitry Andric Config.DumpSection.push_back(Value); 97481ad6265SDimitry Andric } 97581ad6265SDimitry Andric Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all); 97681ad6265SDimitry Andric Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu); 97781ad6265SDimitry Andric Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug); 97881ad6265SDimitry Andric Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo); 97981ad6265SDimitry Andric Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections); 98081ad6265SDimitry Andric Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc); 98181ad6265SDimitry Andric Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded); 98281ad6265SDimitry Andric Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo); 98381ad6265SDimitry Andric Config.ExtractMainPartition = 98481ad6265SDimitry Andric InputArgs.hasArg(OBJCOPY_extract_main_partition); 98581ad6265SDimitry Andric ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden); 98681ad6265SDimitry Andric Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken); 98781ad6265SDimitry Andric if (auto *Arg = 98881ad6265SDimitry Andric InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) { 98981ad6265SDimitry Andric Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all) 99081ad6265SDimitry Andric ? DiscardType::All 99181ad6265SDimitry Andric : DiscardType::Locals; 99281ad6265SDimitry Andric } 993*0fca6ea1SDimitry Andric 994*0fca6ea1SDimitry Andric ELFConfig.VerifyNoteSections = InputArgs.hasFlag( 995*0fca6ea1SDimitry Andric OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true); 996*0fca6ea1SDimitry Andric 99781ad6265SDimitry Andric Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug); 99881ad6265SDimitry Andric ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols); 99981ad6265SDimitry Andric MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined); 100081ad6265SDimitry Andric Config.DecompressDebugSections = 100181ad6265SDimitry Andric InputArgs.hasArg(OBJCOPY_decompress_debug_sections); 100281ad6265SDimitry Andric if (Config.DiscardMode == DiscardType::All) { 100381ad6265SDimitry Andric Config.StripDebug = true; 100481ad6265SDimitry Andric ELFConfig.KeepFileSymbols = true; 100581ad6265SDimitry Andric } 1006bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol)) 100781ad6265SDimitry Andric if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create( 100881ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 100981ad6265SDimitry Andric return std::move(E); 1010bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols)) 101181ad6265SDimitry Andric if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc, 101281ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, 101381ad6265SDimitry Andric ErrorCallback)) 101481ad6265SDimitry Andric return std::move(E); 1015bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol)) 101681ad6265SDimitry Andric if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create( 101781ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 101881ad6265SDimitry Andric return std::move(E); 1019bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols)) 102081ad6265SDimitry Andric if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc, 102181ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, 102281ad6265SDimitry Andric ErrorCallback)) 102381ad6265SDimitry Andric return std::move(E); 1024bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol)) 102581ad6265SDimitry Andric if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create( 102681ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 102781ad6265SDimitry Andric return std::move(E); 1028bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols)) 102981ad6265SDimitry Andric if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc, 103081ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, 103181ad6265SDimitry Andric ErrorCallback)) 103281ad6265SDimitry Andric return std::move(E); 1033bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol)) 103481ad6265SDimitry Andric if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create( 103581ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 103681ad6265SDimitry Andric return std::move(E); 1037bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols)) 103881ad6265SDimitry Andric if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc, 103981ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, 104081ad6265SDimitry Andric ErrorCallback)) 104181ad6265SDimitry Andric return std::move(E); 1042bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol)) 104381ad6265SDimitry Andric if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( 104481ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 104581ad6265SDimitry Andric return std::move(E); 1046bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols)) 104781ad6265SDimitry Andric if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc, 104881ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, 104981ad6265SDimitry Andric ErrorCallback)) 105081ad6265SDimitry Andric return std::move(E); 1051bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol)) 105281ad6265SDimitry Andric if (Error E = 105381ad6265SDimitry Andric Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create( 105481ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 105581ad6265SDimitry Andric return std::move(E); 1056bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols)) 105781ad6265SDimitry Andric if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc, 105881ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, 105981ad6265SDimitry Andric ErrorCallback)) 106081ad6265SDimitry Andric return std::move(E); 1061bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol)) 106281ad6265SDimitry Andric if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create( 106381ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 106481ad6265SDimitry Andric return std::move(E); 1065bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols)) 106681ad6265SDimitry Andric if (Error E = 106781ad6265SDimitry Andric addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(), 106881ad6265SDimitry Andric SymbolMatchStyle, ErrorCallback)) 106981ad6265SDimitry Andric return std::move(E); 1070*0fca6ea1SDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol)) 1071*0fca6ea1SDimitry Andric if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create( 1072*0fca6ea1SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1073*0fca6ea1SDimitry Andric return std::move(E); 1074*0fca6ea1SDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols)) 1075*0fca6ea1SDimitry Andric if (Error E = 1076*0fca6ea1SDimitry Andric addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(), 1077*0fca6ea1SDimitry Andric SymbolMatchStyle, ErrorCallback)) 1078*0fca6ea1SDimitry Andric return std::move(E); 107981ad6265SDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) { 108081ad6265SDimitry Andric Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue()); 108181ad6265SDimitry Andric if (!SymInfo) 108281ad6265SDimitry Andric return SymInfo.takeError(); 108381ad6265SDimitry Andric 108481ad6265SDimitry Andric Config.SymbolsToAdd.push_back(*SymInfo); 108581ad6265SDimitry Andric } 1086*0fca6ea1SDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbol_visibility)) { 1087*0fca6ea1SDimitry Andric if (!StringRef(Arg->getValue()).contains('=')) 1088*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 1089*0fca6ea1SDimitry Andric "bad format for --set-symbol-visibility"); 1090*0fca6ea1SDimitry Andric auto [Sym, Visibility] = StringRef(Arg->getValue()).split('='); 1091*0fca6ea1SDimitry Andric Expected<uint8_t> Type = parseVisibilityType(Visibility); 1092*0fca6ea1SDimitry Andric if (!Type) 1093*0fca6ea1SDimitry Andric return Type.takeError(); 1094*0fca6ea1SDimitry Andric ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type); 1095*0fca6ea1SDimitry Andric if (Error E = ELFConfig.SymbolsToSetVisibility.back().first.addMatcher( 1096*0fca6ea1SDimitry Andric NameOrPattern::create(Sym, SymbolMatchStyle, ErrorCallback))) 1097*0fca6ea1SDimitry Andric return std::move(E); 1098*0fca6ea1SDimitry Andric } 1099*0fca6ea1SDimitry Andric for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbols_visibility)) { 1100*0fca6ea1SDimitry Andric if (!StringRef(Arg->getValue()).contains('=')) 1101*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 1102*0fca6ea1SDimitry Andric "bad format for --set-symbols-visibility"); 1103*0fca6ea1SDimitry Andric auto [File, Visibility] = StringRef(Arg->getValue()).split('='); 1104*0fca6ea1SDimitry Andric Expected<uint8_t> Type = parseVisibilityType(Visibility); 1105*0fca6ea1SDimitry Andric if (!Type) 1106*0fca6ea1SDimitry Andric return Type.takeError(); 1107*0fca6ea1SDimitry Andric ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type); 1108*0fca6ea1SDimitry Andric if (Error E = 1109*0fca6ea1SDimitry Andric addSymbolsFromFile(ELFConfig.SymbolsToSetVisibility.back().first, 1110*0fca6ea1SDimitry Andric DC.Alloc, File, SymbolMatchStyle, ErrorCallback)) 1111*0fca6ea1SDimitry Andric return std::move(E); 1112*0fca6ea1SDimitry Andric } 111381ad6265SDimitry Andric 111481ad6265SDimitry Andric ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links); 111581ad6265SDimitry Andric 111681ad6265SDimitry Andric Config.DeterministicArchives = InputArgs.hasFlag( 111781ad6265SDimitry Andric OBJCOPY_enable_deterministic_archives, 111881ad6265SDimitry Andric OBJCOPY_disable_deterministic_archives, /*default=*/true); 111981ad6265SDimitry Andric 112081ad6265SDimitry Andric Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates); 112181ad6265SDimitry Andric 112281ad6265SDimitry Andric if (Config.PreserveDates && 112381ad6265SDimitry Andric (Config.OutputFilename == "-" || Config.InputFilename == "-")) 112481ad6265SDimitry Andric return createStringError(errc::invalid_argument, 112581ad6265SDimitry Andric "--preserve-dates requires a file"); 112681ad6265SDimitry Andric 1127bdd1243dSDimitry Andric for (auto *Arg : InputArgs) 112881ad6265SDimitry Andric if (Arg->getOption().matches(OBJCOPY_set_start)) { 112981ad6265SDimitry Andric auto EAddr = getAsInteger<uint64_t>(Arg->getValue()); 113081ad6265SDimitry Andric if (!EAddr) 113181ad6265SDimitry Andric return createStringError( 113281ad6265SDimitry Andric EAddr.getError(), "bad entry point address: '%s'", Arg->getValue()); 113381ad6265SDimitry Andric 113481ad6265SDimitry Andric ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; }; 113581ad6265SDimitry Andric } else if (Arg->getOption().matches(OBJCOPY_change_start)) { 113681ad6265SDimitry Andric auto EIncr = getAsInteger<int64_t>(Arg->getValue()); 113781ad6265SDimitry Andric if (!EIncr) 113881ad6265SDimitry Andric return createStringError(EIncr.getError(), 113981ad6265SDimitry Andric "bad entry point increment: '%s'", 114081ad6265SDimitry Andric Arg->getValue()); 114181ad6265SDimitry Andric auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr) 114281ad6265SDimitry Andric : [](uint64_t A) { return A; }; 114381ad6265SDimitry Andric ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) { 114481ad6265SDimitry Andric return Expr(EAddr) + *EIncr; 114581ad6265SDimitry Andric }; 114681ad6265SDimitry Andric } 114781ad6265SDimitry Andric 114881ad6265SDimitry Andric if (Config.DecompressDebugSections && 114981ad6265SDimitry Andric Config.CompressionType != DebugCompressionType::None) { 115081ad6265SDimitry Andric return createStringError( 115181ad6265SDimitry Andric errc::invalid_argument, 115281ad6265SDimitry Andric "cannot specify both --compress-debug-sections and " 115381ad6265SDimitry Andric "--decompress-debug-sections"); 115481ad6265SDimitry Andric } 115581ad6265SDimitry Andric 115681ad6265SDimitry Andric if (Config.ExtractPartition && Config.ExtractMainPartition) 115781ad6265SDimitry Andric return createStringError(errc::invalid_argument, 115881ad6265SDimitry Andric "cannot specify --extract-partition together with " 115981ad6265SDimitry Andric "--extract-main-partition"); 116081ad6265SDimitry Andric 116181ad6265SDimitry Andric DC.CopyConfigs.push_back(std::move(ConfigMgr)); 116281ad6265SDimitry Andric return std::move(DC); 116381ad6265SDimitry Andric } 116481ad6265SDimitry Andric 116581ad6265SDimitry Andric // parseInstallNameToolOptions returns the config and sets the input arguments. 116681ad6265SDimitry Andric // If a help flag is set then parseInstallNameToolOptions will print the help 116781ad6265SDimitry Andric // messege and exit. 116881ad6265SDimitry Andric Expected<DriverConfig> 116981ad6265SDimitry Andric objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) { 117081ad6265SDimitry Andric DriverConfig DC; 117181ad6265SDimitry Andric ConfigManager ConfigMgr; 117281ad6265SDimitry Andric CommonConfig &Config = ConfigMgr.Common; 117381ad6265SDimitry Andric MachOConfig &MachOConfig = ConfigMgr.MachO; 117481ad6265SDimitry Andric InstallNameToolOptTable T; 117581ad6265SDimitry Andric unsigned MissingArgumentIndex, MissingArgumentCount; 117681ad6265SDimitry Andric llvm::opt::InputArgList InputArgs = 117781ad6265SDimitry Andric T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 117881ad6265SDimitry Andric 117981ad6265SDimitry Andric if (MissingArgumentCount) 118081ad6265SDimitry Andric return createStringError( 118181ad6265SDimitry Andric errc::invalid_argument, 118281ad6265SDimitry Andric "missing argument to " + 118381ad6265SDimitry Andric StringRef(InputArgs.getArgString(MissingArgumentIndex)) + 118481ad6265SDimitry Andric " option"); 118581ad6265SDimitry Andric 118681ad6265SDimitry Andric if (InputArgs.size() == 0) { 118781ad6265SDimitry Andric printHelp(T, errs(), ToolType::InstallNameTool); 118881ad6265SDimitry Andric exit(1); 118981ad6265SDimitry Andric } 119081ad6265SDimitry Andric 119181ad6265SDimitry Andric if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) { 119281ad6265SDimitry Andric printHelp(T, outs(), ToolType::InstallNameTool); 119381ad6265SDimitry Andric exit(0); 119481ad6265SDimitry Andric } 119581ad6265SDimitry Andric 119681ad6265SDimitry Andric if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) { 119781ad6265SDimitry Andric outs() << "llvm-install-name-tool, compatible with cctools " 119881ad6265SDimitry Andric "install_name_tool\n"; 119981ad6265SDimitry Andric cl::PrintVersionMessage(); 120081ad6265SDimitry Andric exit(0); 120181ad6265SDimitry Andric } 120281ad6265SDimitry Andric 1203bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath)) 120481ad6265SDimitry Andric MachOConfig.RPathToAdd.push_back(Arg->getValue()); 120581ad6265SDimitry Andric 120681ad6265SDimitry Andric for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath)) 120781ad6265SDimitry Andric MachOConfig.RPathToPrepend.push_back(Arg->getValue()); 120881ad6265SDimitry Andric 1209bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) { 121081ad6265SDimitry Andric StringRef RPath = Arg->getValue(); 121181ad6265SDimitry Andric 121281ad6265SDimitry Andric // Cannot add and delete the same rpath at the same time. 121381ad6265SDimitry Andric if (is_contained(MachOConfig.RPathToAdd, RPath)) 121481ad6265SDimitry Andric return createStringError( 121581ad6265SDimitry Andric errc::invalid_argument, 121681ad6265SDimitry Andric "cannot specify both -add_rpath '%s' and -delete_rpath '%s'", 121781ad6265SDimitry Andric RPath.str().c_str(), RPath.str().c_str()); 121881ad6265SDimitry Andric if (is_contained(MachOConfig.RPathToPrepend, RPath)) 121981ad6265SDimitry Andric return createStringError( 122081ad6265SDimitry Andric errc::invalid_argument, 122181ad6265SDimitry Andric "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'", 122281ad6265SDimitry Andric RPath.str().c_str(), RPath.str().c_str()); 122381ad6265SDimitry Andric 122481ad6265SDimitry Andric MachOConfig.RPathsToRemove.insert(RPath); 122581ad6265SDimitry Andric } 122681ad6265SDimitry Andric 122781ad6265SDimitry Andric for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) { 122881ad6265SDimitry Andric StringRef Old = Arg->getValue(0); 122981ad6265SDimitry Andric StringRef New = Arg->getValue(1); 123081ad6265SDimitry Andric 123181ad6265SDimitry Andric auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; }; 123281ad6265SDimitry Andric 123381ad6265SDimitry Andric // Cannot specify duplicate -rpath entries 123481ad6265SDimitry Andric auto It1 = find_if( 123581ad6265SDimitry Andric MachOConfig.RPathsToUpdate, 123681ad6265SDimitry Andric [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) { 123781ad6265SDimitry Andric return Match(OldNew.getFirst()) || Match(OldNew.getSecond()); 123881ad6265SDimitry Andric }); 123981ad6265SDimitry Andric if (It1 != MachOConfig.RPathsToUpdate.end()) 124081ad6265SDimitry Andric return createStringError(errc::invalid_argument, 124181ad6265SDimitry Andric "cannot specify both -rpath '" + 124281ad6265SDimitry Andric It1->getFirst() + "' '" + It1->getSecond() + 124381ad6265SDimitry Andric "' and -rpath '" + Old + "' '" + New + "'"); 124481ad6265SDimitry Andric 124581ad6265SDimitry Andric // Cannot specify the same rpath under both -delete_rpath and -rpath 124681ad6265SDimitry Andric auto It2 = find_if(MachOConfig.RPathsToRemove, Match); 124781ad6265SDimitry Andric if (It2 != MachOConfig.RPathsToRemove.end()) 124881ad6265SDimitry Andric return createStringError(errc::invalid_argument, 124981ad6265SDimitry Andric "cannot specify both -delete_rpath '" + *It2 + 125081ad6265SDimitry Andric "' and -rpath '" + Old + "' '" + New + "'"); 125181ad6265SDimitry Andric 125281ad6265SDimitry Andric // Cannot specify the same rpath under both -add_rpath and -rpath 125381ad6265SDimitry Andric auto It3 = find_if(MachOConfig.RPathToAdd, Match); 125481ad6265SDimitry Andric if (It3 != MachOConfig.RPathToAdd.end()) 125581ad6265SDimitry Andric return createStringError(errc::invalid_argument, 125681ad6265SDimitry Andric "cannot specify both -add_rpath '" + *It3 + 125781ad6265SDimitry Andric "' and -rpath '" + Old + "' '" + New + "'"); 125881ad6265SDimitry Andric 125981ad6265SDimitry Andric // Cannot specify the same rpath under both -prepend_rpath and -rpath. 126081ad6265SDimitry Andric auto It4 = find_if(MachOConfig.RPathToPrepend, Match); 126181ad6265SDimitry Andric if (It4 != MachOConfig.RPathToPrepend.end()) 126281ad6265SDimitry Andric return createStringError(errc::invalid_argument, 126381ad6265SDimitry Andric "cannot specify both -prepend_rpath '" + *It4 + 126481ad6265SDimitry Andric "' and -rpath '" + Old + "' '" + New + "'"); 126581ad6265SDimitry Andric 126681ad6265SDimitry Andric MachOConfig.RPathsToUpdate.insert({Old, New}); 126781ad6265SDimitry Andric } 126881ad6265SDimitry Andric 126981ad6265SDimitry Andric if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) { 127081ad6265SDimitry Andric MachOConfig.SharedLibId = Arg->getValue(); 127181ad6265SDimitry Andric if (MachOConfig.SharedLibId->empty()) 127281ad6265SDimitry Andric return createStringError(errc::invalid_argument, 127381ad6265SDimitry Andric "cannot specify an empty id"); 127481ad6265SDimitry Andric } 127581ad6265SDimitry Andric 127681ad6265SDimitry Andric for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change)) 127781ad6265SDimitry Andric MachOConfig.InstallNamesToUpdate.insert( 127881ad6265SDimitry Andric {Arg->getValue(0), Arg->getValue(1)}); 127981ad6265SDimitry Andric 128081ad6265SDimitry Andric MachOConfig.RemoveAllRpaths = 128181ad6265SDimitry Andric InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths); 128281ad6265SDimitry Andric 128381ad6265SDimitry Andric SmallVector<StringRef, 2> Positional; 1284bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN)) 128581ad6265SDimitry Andric return createStringError(errc::invalid_argument, "unknown argument '%s'", 128681ad6265SDimitry Andric Arg->getAsString(InputArgs).c_str()); 1287bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT)) 128881ad6265SDimitry Andric Positional.push_back(Arg->getValue()); 128981ad6265SDimitry Andric if (Positional.empty()) 129081ad6265SDimitry Andric return createStringError(errc::invalid_argument, "no input file specified"); 129181ad6265SDimitry Andric if (Positional.size() > 1) 129281ad6265SDimitry Andric return createStringError( 129381ad6265SDimitry Andric errc::invalid_argument, 129481ad6265SDimitry Andric "llvm-install-name-tool expects a single input file"); 129581ad6265SDimitry Andric Config.InputFilename = Positional[0]; 129681ad6265SDimitry Andric Config.OutputFilename = Positional[0]; 129781ad6265SDimitry Andric 1298*0fca6ea1SDimitry Andric Expected<OwningBinary<Binary>> BinaryOrErr = 1299*0fca6ea1SDimitry Andric createBinary(Config.InputFilename); 1300*0fca6ea1SDimitry Andric if (!BinaryOrErr) 1301*0fca6ea1SDimitry Andric return createFileError(Config.InputFilename, BinaryOrErr.takeError()); 1302*0fca6ea1SDimitry Andric auto *Binary = (*BinaryOrErr).getBinary(); 1303*0fca6ea1SDimitry Andric if (!Binary->isMachO() && !Binary->isMachOUniversalBinary()) 1304*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 1305*0fca6ea1SDimitry Andric "input file: %s is not a Mach-O file", 1306*0fca6ea1SDimitry Andric Config.InputFilename.str().c_str()); 1307*0fca6ea1SDimitry Andric 130881ad6265SDimitry Andric DC.CopyConfigs.push_back(std::move(ConfigMgr)); 130981ad6265SDimitry Andric return std::move(DC); 131081ad6265SDimitry Andric } 131181ad6265SDimitry Andric 131281ad6265SDimitry Andric Expected<DriverConfig> 131381ad6265SDimitry Andric objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr, 131481ad6265SDimitry Andric function_ref<Error(Error)> ErrorCallback) { 131581ad6265SDimitry Andric DriverConfig DC; 131681ad6265SDimitry Andric ConfigManager ConfigMgr; 131781ad6265SDimitry Andric CommonConfig &Config = ConfigMgr.Common; 131881ad6265SDimitry Andric MachOConfig &MachOConfig = ConfigMgr.MachO; 131981ad6265SDimitry Andric BitcodeStripOptTable T; 132081ad6265SDimitry Andric unsigned MissingArgumentIndex, MissingArgumentCount; 132181ad6265SDimitry Andric opt::InputArgList InputArgs = 132281ad6265SDimitry Andric T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 132381ad6265SDimitry Andric 132481ad6265SDimitry Andric if (InputArgs.size() == 0) { 132581ad6265SDimitry Andric printHelp(T, errs(), ToolType::BitcodeStrip); 132681ad6265SDimitry Andric exit(1); 132781ad6265SDimitry Andric } 132881ad6265SDimitry Andric 132981ad6265SDimitry Andric if (InputArgs.hasArg(BITCODE_STRIP_help)) { 133081ad6265SDimitry Andric printHelp(T, outs(), ToolType::BitcodeStrip); 133181ad6265SDimitry Andric exit(0); 133281ad6265SDimitry Andric } 133381ad6265SDimitry Andric 133481ad6265SDimitry Andric if (InputArgs.hasArg(BITCODE_STRIP_version)) { 133581ad6265SDimitry Andric outs() << "llvm-bitcode-strip, compatible with cctools " 133681ad6265SDimitry Andric "bitcode_strip\n"; 133781ad6265SDimitry Andric cl::PrintVersionMessage(); 133881ad6265SDimitry Andric exit(0); 133981ad6265SDimitry Andric } 134081ad6265SDimitry Andric 134181ad6265SDimitry Andric for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN)) 134281ad6265SDimitry Andric return createStringError(errc::invalid_argument, "unknown argument '%s'", 134381ad6265SDimitry Andric Arg->getAsString(InputArgs).c_str()); 134481ad6265SDimitry Andric 134581ad6265SDimitry Andric SmallVector<StringRef, 2> Positional; 134681ad6265SDimitry Andric for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT)) 134781ad6265SDimitry Andric Positional.push_back(Arg->getValue()); 134881ad6265SDimitry Andric if (Positional.size() > 1) 134981ad6265SDimitry Andric return createStringError(errc::invalid_argument, 135081ad6265SDimitry Andric "llvm-bitcode-strip expects a single input file"); 135181ad6265SDimitry Andric assert(!Positional.empty()); 135281ad6265SDimitry Andric Config.InputFilename = Positional[0]; 135381ad6265SDimitry Andric 135481ad6265SDimitry Andric if (!InputArgs.hasArg(BITCODE_STRIP_output)) { 135581ad6265SDimitry Andric return createStringError(errc::invalid_argument, 135681ad6265SDimitry Andric "-o is a required argument"); 135781ad6265SDimitry Andric } 135881ad6265SDimitry Andric Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output); 135981ad6265SDimitry Andric 136081ad6265SDimitry Andric if (!InputArgs.hasArg(BITCODE_STRIP_remove)) 136181ad6265SDimitry Andric return createStringError(errc::invalid_argument, "no action specified"); 136281ad6265SDimitry Andric 136381ad6265SDimitry Andric // We only support -r for now, which removes all bitcode sections and 136481ad6265SDimitry Andric // the __LLVM segment if it's now empty. 136581ad6265SDimitry Andric cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1366bdd1243dSDimitry Andric "__LLVM,__asm", MatchStyle::Literal, ErrorCallback))); 1367bdd1243dSDimitry Andric cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1368bdd1243dSDimitry Andric "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback))); 1369bdd1243dSDimitry Andric cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 137081ad6265SDimitry Andric "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback))); 1371bdd1243dSDimitry Andric cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1372bdd1243dSDimitry Andric "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback))); 1373bdd1243dSDimitry Andric cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1374bdd1243dSDimitry Andric "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback))); 137581ad6265SDimitry Andric MachOConfig.EmptySegmentsToRemove.insert("__LLVM"); 137681ad6265SDimitry Andric 137781ad6265SDimitry Andric DC.CopyConfigs.push_back(std::move(ConfigMgr)); 137881ad6265SDimitry Andric return std::move(DC); 137981ad6265SDimitry Andric } 138081ad6265SDimitry Andric 138181ad6265SDimitry Andric // parseStripOptions returns the config and sets the input arguments. If a 138281ad6265SDimitry Andric // help flag is set then parseStripOptions will print the help messege and 138381ad6265SDimitry Andric // exit. 138481ad6265SDimitry Andric Expected<DriverConfig> 138581ad6265SDimitry Andric objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr, 138681ad6265SDimitry Andric function_ref<Error(Error)> ErrorCallback) { 138781ad6265SDimitry Andric const char *const *DashDash = 1388bdd1243dSDimitry Andric llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; }); 1389bdd1243dSDimitry Andric ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash); 139081ad6265SDimitry Andric if (DashDash != RawArgsArr.end()) 139181ad6265SDimitry Andric DashDash = std::next(DashDash); 139281ad6265SDimitry Andric 139381ad6265SDimitry Andric StripOptTable T; 139481ad6265SDimitry Andric unsigned MissingArgumentIndex, MissingArgumentCount; 139581ad6265SDimitry Andric llvm::opt::InputArgList InputArgs = 139681ad6265SDimitry Andric T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 139781ad6265SDimitry Andric 139881ad6265SDimitry Andric if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) { 139981ad6265SDimitry Andric printHelp(T, errs(), ToolType::Strip); 140081ad6265SDimitry Andric exit(1); 140181ad6265SDimitry Andric } 140281ad6265SDimitry Andric 140381ad6265SDimitry Andric if (InputArgs.hasArg(STRIP_help)) { 140481ad6265SDimitry Andric printHelp(T, outs(), ToolType::Strip); 140581ad6265SDimitry Andric exit(0); 140681ad6265SDimitry Andric } 140781ad6265SDimitry Andric 140881ad6265SDimitry Andric if (InputArgs.hasArg(STRIP_version)) { 140981ad6265SDimitry Andric outs() << "llvm-strip, compatible with GNU strip\n"; 141081ad6265SDimitry Andric cl::PrintVersionMessage(); 141181ad6265SDimitry Andric exit(0); 141281ad6265SDimitry Andric } 141381ad6265SDimitry Andric 141481ad6265SDimitry Andric SmallVector<StringRef, 2> Positional; 1415bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN)) 141681ad6265SDimitry Andric return createStringError(errc::invalid_argument, "unknown argument '%s'", 141781ad6265SDimitry Andric Arg->getAsString(InputArgs).c_str()); 1418bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(STRIP_INPUT)) 141981ad6265SDimitry Andric Positional.push_back(Arg->getValue()); 142081ad6265SDimitry Andric std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional)); 142181ad6265SDimitry Andric 142281ad6265SDimitry Andric if (Positional.empty()) 142381ad6265SDimitry Andric return createStringError(errc::invalid_argument, "no input file specified"); 142481ad6265SDimitry Andric 142581ad6265SDimitry Andric if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output)) 142681ad6265SDimitry Andric return createStringError( 142781ad6265SDimitry Andric errc::invalid_argument, 142881ad6265SDimitry Andric "multiple input files cannot be used in combination with -o"); 142981ad6265SDimitry Andric 143081ad6265SDimitry Andric ConfigManager ConfigMgr; 143181ad6265SDimitry Andric CommonConfig &Config = ConfigMgr.Common; 143281ad6265SDimitry Andric ELFConfig &ELFConfig = ConfigMgr.ELF; 143381ad6265SDimitry Andric MachOConfig &MachOConfig = ConfigMgr.MachO; 143481ad6265SDimitry Andric 143581ad6265SDimitry Andric if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard)) 143681ad6265SDimitry Andric return createStringError(errc::invalid_argument, 143781ad6265SDimitry Andric "--regex and --wildcard are incompatible"); 143881ad6265SDimitry Andric MatchStyle SectionMatchStyle = 143981ad6265SDimitry Andric InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard; 144081ad6265SDimitry Andric MatchStyle SymbolMatchStyle 144181ad6265SDimitry Andric = InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex 144281ad6265SDimitry Andric : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard 144381ad6265SDimitry Andric : MatchStyle::Literal; 144481ad6265SDimitry Andric ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links); 144581ad6265SDimitry Andric Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug); 144681ad6265SDimitry Andric 144781ad6265SDimitry Andric if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals)) 144881ad6265SDimitry Andric Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all) 144981ad6265SDimitry Andric ? DiscardType::All 145081ad6265SDimitry Andric : DiscardType::Locals; 145181ad6265SDimitry Andric Config.StripSections = InputArgs.hasArg(STRIP_strip_sections); 145281ad6265SDimitry Andric Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded); 145381ad6265SDimitry Andric if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all)) 145481ad6265SDimitry Andric Config.StripAll = Arg->getOption().getID() == STRIP_strip_all; 145581ad6265SDimitry Andric Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu); 145681ad6265SDimitry Andric MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols); 145781ad6265SDimitry Andric Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug); 145881ad6265SDimitry Andric ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols); 145981ad6265SDimitry Andric MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined); 146081ad6265SDimitry Andric 1461bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(STRIP_keep_section)) 146281ad6265SDimitry Andric if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( 146381ad6265SDimitry Andric Arg->getValue(), SectionMatchStyle, ErrorCallback))) 146481ad6265SDimitry Andric return std::move(E); 146581ad6265SDimitry Andric 1466bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(STRIP_remove_section)) 146781ad6265SDimitry Andric if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( 146881ad6265SDimitry Andric Arg->getValue(), SectionMatchStyle, ErrorCallback))) 146981ad6265SDimitry Andric return std::move(E); 147081ad6265SDimitry Andric 1471bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol)) 147281ad6265SDimitry Andric if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( 147381ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 147481ad6265SDimitry Andric return std::move(E); 147581ad6265SDimitry Andric 1476bdd1243dSDimitry Andric for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol)) 147781ad6265SDimitry Andric if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create( 147881ad6265SDimitry Andric Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 147981ad6265SDimitry Andric return std::move(E); 148081ad6265SDimitry Andric 148181ad6265SDimitry Andric if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug && 148281ad6265SDimitry Andric !Config.OnlyKeepDebug && !Config.StripUnneeded && 148381ad6265SDimitry Andric Config.DiscardMode == DiscardType::None && !Config.StripAllGNU && 148481ad6265SDimitry Andric Config.SymbolsToRemove.empty()) 148581ad6265SDimitry Andric Config.StripAll = true; 148681ad6265SDimitry Andric 148781ad6265SDimitry Andric if (Config.DiscardMode == DiscardType::All) { 148881ad6265SDimitry Andric Config.StripDebug = true; 148981ad6265SDimitry Andric ELFConfig.KeepFileSymbols = true; 149081ad6265SDimitry Andric } 149181ad6265SDimitry Andric 149281ad6265SDimitry Andric Config.DeterministicArchives = 149381ad6265SDimitry Andric InputArgs.hasFlag(STRIP_enable_deterministic_archives, 149481ad6265SDimitry Andric STRIP_disable_deterministic_archives, /*default=*/true); 149581ad6265SDimitry Andric 149681ad6265SDimitry Andric Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates); 149781ad6265SDimitry Andric Config.InputFormat = FileFormat::Unspecified; 149881ad6265SDimitry Andric Config.OutputFormat = FileFormat::Unspecified; 149981ad6265SDimitry Andric 150081ad6265SDimitry Andric DriverConfig DC; 150181ad6265SDimitry Andric if (Positional.size() == 1) { 150281ad6265SDimitry Andric Config.InputFilename = Positional[0]; 150381ad6265SDimitry Andric Config.OutputFilename = 150481ad6265SDimitry Andric InputArgs.getLastArgValue(STRIP_output, Positional[0]); 150581ad6265SDimitry Andric DC.CopyConfigs.push_back(std::move(ConfigMgr)); 150681ad6265SDimitry Andric } else { 150781ad6265SDimitry Andric StringMap<unsigned> InputFiles; 150881ad6265SDimitry Andric for (StringRef Filename : Positional) { 150981ad6265SDimitry Andric if (InputFiles[Filename]++ == 1) { 151081ad6265SDimitry Andric if (Filename == "-") 151181ad6265SDimitry Andric return createStringError( 151281ad6265SDimitry Andric errc::invalid_argument, 151381ad6265SDimitry Andric "cannot specify '-' as an input file more than once"); 151481ad6265SDimitry Andric if (Error E = ErrorCallback(createStringError( 151581ad6265SDimitry Andric errc::invalid_argument, "'%s' was already specified", 151681ad6265SDimitry Andric Filename.str().c_str()))) 151781ad6265SDimitry Andric return std::move(E); 151881ad6265SDimitry Andric } 151981ad6265SDimitry Andric Config.InputFilename = Filename; 152081ad6265SDimitry Andric Config.OutputFilename = Filename; 152181ad6265SDimitry Andric DC.CopyConfigs.push_back(ConfigMgr); 152281ad6265SDimitry Andric } 152381ad6265SDimitry Andric } 152481ad6265SDimitry Andric 152581ad6265SDimitry Andric if (Config.PreserveDates && (is_contained(Positional, "-") || 152681ad6265SDimitry Andric InputArgs.getLastArgValue(STRIP_output) == "-")) 152781ad6265SDimitry Andric return createStringError(errc::invalid_argument, 152881ad6265SDimitry Andric "--preserve-dates requires a file"); 152981ad6265SDimitry Andric 153081ad6265SDimitry Andric return std::move(DC); 153181ad6265SDimitry Andric } 1532