1f75da0c8SAlexey Lapshin //===- ObjcopyOptions.cpp -------------------------------------------------===// 2f75da0c8SAlexey Lapshin // 3f75da0c8SAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f75da0c8SAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information. 5f75da0c8SAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f75da0c8SAlexey Lapshin // 7f75da0c8SAlexey Lapshin //===----------------------------------------------------------------------===// 8f75da0c8SAlexey Lapshin 9f75da0c8SAlexey Lapshin #include "ObjcopyOptions.h" 10f75da0c8SAlexey Lapshin #include "llvm/ADT/SmallVector.h" 11b0abd489SElliot Goodrich #include "llvm/ADT/StringExtras.h" 12f75da0c8SAlexey Lapshin #include "llvm/ADT/StringRef.h" 130d98582cSFangrui Song #include "llvm/ADT/StringSwitch.h" 14f75da0c8SAlexey Lapshin #include "llvm/BinaryFormat/COFF.h" 1594fba14fSRichard Howell #include "llvm/ObjCopy/CommonConfig.h" 16f75da0c8SAlexey Lapshin #include "llvm/ObjCopy/ConfigManager.h" 1759172194SRichard Howell #include "llvm/ObjCopy/MachO/MachOConfig.h" 18fa535452SKeith Smiley #include "llvm/Object/Binary.h" 19f75da0c8SAlexey Lapshin #include "llvm/Option/Arg.h" 20f75da0c8SAlexey Lapshin #include "llvm/Option/ArgList.h" 21f75da0c8SAlexey Lapshin #include "llvm/Support/CRC.h" 22f75da0c8SAlexey Lapshin #include "llvm/Support/CommandLine.h" 23f75da0c8SAlexey Lapshin #include "llvm/Support/Compression.h" 24f75da0c8SAlexey Lapshin #include "llvm/Support/Errc.h" 25f75da0c8SAlexey Lapshin #include "llvm/Support/Error.h" 26f75da0c8SAlexey Lapshin #include "llvm/Support/MemoryBuffer.h" 27f75da0c8SAlexey Lapshin 28f75da0c8SAlexey Lapshin using namespace llvm; 29f75da0c8SAlexey Lapshin using namespace llvm::objcopy; 30fa535452SKeith Smiley using namespace llvm::object; 31dcb6d212SJustin Bogner using namespace llvm::opt; 32f75da0c8SAlexey Lapshin 33f75da0c8SAlexey Lapshin namespace { 34f75da0c8SAlexey Lapshin enum ObjcopyID { 35f75da0c8SAlexey Lapshin OBJCOPY_INVALID = 0, // This is not an option ID. 363f092f37SJan Svoboda #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__), 37f75da0c8SAlexey Lapshin #include "ObjcopyOpts.inc" 38f75da0c8SAlexey Lapshin #undef OPTION 39f75da0c8SAlexey Lapshin }; 40f75da0c8SAlexey Lapshin 41d9ab3e82Sserge-sans-paille namespace objcopy_opt { 42dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE 43f75da0c8SAlexey Lapshin #include "ObjcopyOpts.inc" 44dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE 45dd647e3eSChandler Carruth 46dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE 47dd647e3eSChandler Carruth #include "ObjcopyOpts.inc" 48dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE 49f75da0c8SAlexey Lapshin 5007d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info ObjcopyInfoTable[] = { 513f092f37SJan Svoboda #define OPTION(...) \ 523f092f37SJan Svoboda LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__), 53f75da0c8SAlexey Lapshin #include "ObjcopyOpts.inc" 54f75da0c8SAlexey Lapshin #undef OPTION 55f75da0c8SAlexey Lapshin }; 56d9ab3e82Sserge-sans-paille } // namespace objcopy_opt 57f75da0c8SAlexey Lapshin 5807bb29d8Sserge-sans-paille class ObjcopyOptTable : public opt::GenericOptTable { 59f75da0c8SAlexey Lapshin public: 60dd647e3eSChandler Carruth ObjcopyOptTable() 61dd647e3eSChandler Carruth : opt::GenericOptTable(objcopy_opt::OptionStrTable, 62dd647e3eSChandler Carruth objcopy_opt::OptionPrefixesTable, 63dd647e3eSChandler Carruth objcopy_opt::ObjcopyInfoTable) { 64f75da0c8SAlexey Lapshin setGroupedShortOptions(true); 652444b6f0SFangrui Song setDashDashParsing(true); 66f75da0c8SAlexey Lapshin } 67f75da0c8SAlexey Lapshin }; 68f75da0c8SAlexey Lapshin 69f75da0c8SAlexey Lapshin enum InstallNameToolID { 70f75da0c8SAlexey Lapshin INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID. 713f092f37SJan Svoboda #define OPTION(...) \ 723f092f37SJan Svoboda LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__), 73f75da0c8SAlexey Lapshin #include "InstallNameToolOpts.inc" 74f75da0c8SAlexey Lapshin #undef OPTION 75f75da0c8SAlexey Lapshin }; 76f75da0c8SAlexey Lapshin 77d9ab3e82Sserge-sans-paille namespace install_name_tool { 78dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE 79f75da0c8SAlexey Lapshin #include "InstallNameToolOpts.inc" 80dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE 81dd647e3eSChandler Carruth 82dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE 83dd647e3eSChandler Carruth #include "InstallNameToolOpts.inc" 84dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE 85f75da0c8SAlexey Lapshin 8607d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = { 873f092f37SJan Svoboda #define OPTION(...) \ 883f092f37SJan Svoboda LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__), 89f75da0c8SAlexey Lapshin #include "InstallNameToolOpts.inc" 90f75da0c8SAlexey Lapshin #undef OPTION 91f75da0c8SAlexey Lapshin }; 92d9ab3e82Sserge-sans-paille } // namespace install_name_tool 93f75da0c8SAlexey Lapshin 9407bb29d8Sserge-sans-paille class InstallNameToolOptTable : public opt::GenericOptTable { 95f75da0c8SAlexey Lapshin public: 96d9ab3e82Sserge-sans-paille InstallNameToolOptTable() 97dd647e3eSChandler Carruth : GenericOptTable(install_name_tool::OptionStrTable, 98dd647e3eSChandler Carruth install_name_tool::OptionPrefixesTable, 99dd647e3eSChandler Carruth install_name_tool::InstallNameToolInfoTable) {} 100f75da0c8SAlexey Lapshin }; 101f75da0c8SAlexey Lapshin 102f75da0c8SAlexey Lapshin enum BitcodeStripID { 103f75da0c8SAlexey Lapshin BITCODE_STRIP_INVALID = 0, // This is not an option ID. 1043f092f37SJan Svoboda #define OPTION(...) \ 1053f092f37SJan Svoboda LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__), 106f75da0c8SAlexey Lapshin #include "BitcodeStripOpts.inc" 107f75da0c8SAlexey Lapshin #undef OPTION 108f75da0c8SAlexey Lapshin }; 109f75da0c8SAlexey Lapshin 110d9ab3e82Sserge-sans-paille namespace bitcode_strip { 111dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE 112f75da0c8SAlexey Lapshin #include "BitcodeStripOpts.inc" 113dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE 114dd647e3eSChandler Carruth 115dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE 116dd647e3eSChandler Carruth #include "BitcodeStripOpts.inc" 117dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE 118f75da0c8SAlexey Lapshin 11907d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = { 1203f092f37SJan Svoboda #define OPTION(...) \ 1213f092f37SJan Svoboda LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__), 122f75da0c8SAlexey Lapshin #include "BitcodeStripOpts.inc" 123f75da0c8SAlexey Lapshin #undef OPTION 124f75da0c8SAlexey Lapshin }; 125d9ab3e82Sserge-sans-paille } // namespace bitcode_strip 126f75da0c8SAlexey Lapshin 12707bb29d8Sserge-sans-paille class BitcodeStripOptTable : public opt::GenericOptTable { 128f75da0c8SAlexey Lapshin public: 12907bb29d8Sserge-sans-paille BitcodeStripOptTable() 130dd647e3eSChandler Carruth : opt::GenericOptTable(bitcode_strip::OptionStrTable, 131dd647e3eSChandler Carruth bitcode_strip::OptionPrefixesTable, 132dd647e3eSChandler Carruth bitcode_strip::BitcodeStripInfoTable) {} 133f75da0c8SAlexey Lapshin }; 134f75da0c8SAlexey Lapshin 135f75da0c8SAlexey Lapshin enum StripID { 136f75da0c8SAlexey Lapshin STRIP_INVALID = 0, // This is not an option ID. 1373f092f37SJan Svoboda #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__), 138f75da0c8SAlexey Lapshin #include "StripOpts.inc" 139f75da0c8SAlexey Lapshin #undef OPTION 140f75da0c8SAlexey Lapshin }; 141f75da0c8SAlexey Lapshin 142d9ab3e82Sserge-sans-paille namespace strip { 143dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE 144f75da0c8SAlexey Lapshin #include "StripOpts.inc" 145dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE 146dd647e3eSChandler Carruth 147dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE 148dd647e3eSChandler Carruth #include "StripOpts.inc" 149dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE 150f75da0c8SAlexey Lapshin 15107d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info StripInfoTable[] = { 1523f092f37SJan Svoboda #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__), 153f75da0c8SAlexey Lapshin #include "StripOpts.inc" 154f75da0c8SAlexey Lapshin #undef OPTION 155f75da0c8SAlexey Lapshin }; 156d9ab3e82Sserge-sans-paille } // namespace strip 157f75da0c8SAlexey Lapshin 15807bb29d8Sserge-sans-paille class StripOptTable : public opt::GenericOptTable { 159f75da0c8SAlexey Lapshin public: 160dd647e3eSChandler Carruth StripOptTable() 161dd647e3eSChandler Carruth : GenericOptTable(strip::OptionStrTable, strip::OptionPrefixesTable, 162dd647e3eSChandler Carruth strip::StripInfoTable) { 163d9ab3e82Sserge-sans-paille setGroupedShortOptions(true); 164d9ab3e82Sserge-sans-paille } 165f75da0c8SAlexey Lapshin }; 166f75da0c8SAlexey Lapshin 167f75da0c8SAlexey Lapshin } // namespace 168f75da0c8SAlexey Lapshin 169f75da0c8SAlexey Lapshin static SectionFlag parseSectionRenameFlag(StringRef SectionName) { 170f75da0c8SAlexey Lapshin return llvm::StringSwitch<SectionFlag>(SectionName) 171f75da0c8SAlexey Lapshin .CaseLower("alloc", SectionFlag::SecAlloc) 172f75da0c8SAlexey Lapshin .CaseLower("load", SectionFlag::SecLoad) 173f75da0c8SAlexey Lapshin .CaseLower("noload", SectionFlag::SecNoload) 174f75da0c8SAlexey Lapshin .CaseLower("readonly", SectionFlag::SecReadonly) 175f75da0c8SAlexey Lapshin .CaseLower("debug", SectionFlag::SecDebug) 176f75da0c8SAlexey Lapshin .CaseLower("code", SectionFlag::SecCode) 177f75da0c8SAlexey Lapshin .CaseLower("data", SectionFlag::SecData) 178f75da0c8SAlexey Lapshin .CaseLower("rom", SectionFlag::SecRom) 179f75da0c8SAlexey Lapshin .CaseLower("merge", SectionFlag::SecMerge) 180f75da0c8SAlexey Lapshin .CaseLower("strings", SectionFlag::SecStrings) 181f75da0c8SAlexey Lapshin .CaseLower("contents", SectionFlag::SecContents) 182f75da0c8SAlexey Lapshin .CaseLower("share", SectionFlag::SecShare) 183f75da0c8SAlexey Lapshin .CaseLower("exclude", SectionFlag::SecExclude) 1846f1395a1SThomas Köppe .CaseLower("large", SectionFlag::SecLarge) 185f75da0c8SAlexey Lapshin .Default(SectionFlag::SecNone); 186f75da0c8SAlexey Lapshin } 187f75da0c8SAlexey Lapshin 188f75da0c8SAlexey Lapshin static Expected<SectionFlag> 189f75da0c8SAlexey Lapshin parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) { 190f75da0c8SAlexey Lapshin SectionFlag ParsedFlags = SectionFlag::SecNone; 191f75da0c8SAlexey Lapshin for (StringRef Flag : SectionFlags) { 192f75da0c8SAlexey Lapshin SectionFlag ParsedFlag = parseSectionRenameFlag(Flag); 193f75da0c8SAlexey Lapshin if (ParsedFlag == SectionFlag::SecNone) 194f75da0c8SAlexey Lapshin return createStringError( 195f75da0c8SAlexey Lapshin errc::invalid_argument, 196f75da0c8SAlexey Lapshin "unrecognized section flag '%s'. Flags supported for GNU " 197f75da0c8SAlexey Lapshin "compatibility: alloc, load, noload, readonly, exclude, debug, " 1986f1395a1SThomas Köppe "code, data, rom, share, contents, merge, strings, large", 199f75da0c8SAlexey Lapshin Flag.str().c_str()); 200f75da0c8SAlexey Lapshin ParsedFlags |= ParsedFlag; 201f75da0c8SAlexey Lapshin } 202f75da0c8SAlexey Lapshin 203f75da0c8SAlexey Lapshin return ParsedFlags; 204f75da0c8SAlexey Lapshin } 205f75da0c8SAlexey Lapshin 206f75da0c8SAlexey Lapshin static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) { 207f75da0c8SAlexey Lapshin if (!FlagValue.contains('=')) 208f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 209f75da0c8SAlexey Lapshin "bad format for --rename-section: missing '='"); 210f75da0c8SAlexey Lapshin 211f75da0c8SAlexey Lapshin // Initial split: ".foo" = ".bar,f1,f2,..." 212f75da0c8SAlexey Lapshin auto Old2New = FlagValue.split('='); 213f75da0c8SAlexey Lapshin SectionRename SR; 214f75da0c8SAlexey Lapshin SR.OriginalName = Old2New.first; 215f75da0c8SAlexey Lapshin 216f75da0c8SAlexey Lapshin // Flags split: ".bar" "f1" "f2" ... 217f75da0c8SAlexey Lapshin SmallVector<StringRef, 6> NameAndFlags; 218f75da0c8SAlexey Lapshin Old2New.second.split(NameAndFlags, ','); 219f75da0c8SAlexey Lapshin SR.NewName = NameAndFlags[0]; 220f75da0c8SAlexey Lapshin 221f75da0c8SAlexey Lapshin if (NameAndFlags.size() > 1) { 222f75da0c8SAlexey Lapshin Expected<SectionFlag> ParsedFlagSet = 22338818b60Sserge-sans-paille parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front()); 224f75da0c8SAlexey Lapshin if (!ParsedFlagSet) 225f75da0c8SAlexey Lapshin return ParsedFlagSet.takeError(); 226f75da0c8SAlexey Lapshin SR.NewFlags = *ParsedFlagSet; 227f75da0c8SAlexey Lapshin } 228f75da0c8SAlexey Lapshin 229f75da0c8SAlexey Lapshin return SR; 230f75da0c8SAlexey Lapshin } 231f75da0c8SAlexey Lapshin 232f75da0c8SAlexey Lapshin static Expected<std::pair<StringRef, uint64_t>> 233b28412d5SFangrui Song parseSetSectionAttribute(StringRef Option, StringRef FlagValue) { 234f75da0c8SAlexey Lapshin if (!FlagValue.contains('=')) 235b28412d5SFangrui Song return make_error<StringError>("bad format for " + Option + ": missing '='", 236b28412d5SFangrui Song errc::invalid_argument); 237f75da0c8SAlexey Lapshin auto Split = StringRef(FlagValue).split('='); 238f75da0c8SAlexey Lapshin if (Split.first.empty()) 239b28412d5SFangrui Song return make_error<StringError>("bad format for " + Option + 240b28412d5SFangrui Song ": missing section name", 241b28412d5SFangrui Song errc::invalid_argument); 242b28412d5SFangrui Song uint64_t Value; 243b28412d5SFangrui Song if (Split.second.getAsInteger(0, Value)) 244b28412d5SFangrui Song return make_error<StringError>("invalid value for " + Option + ": '" + 245b28412d5SFangrui Song Split.second + "'", 246b28412d5SFangrui Song errc::invalid_argument); 247b28412d5SFangrui Song return std::make_pair(Split.first, Value); 248f75da0c8SAlexey Lapshin } 249f75da0c8SAlexey Lapshin 250f75da0c8SAlexey Lapshin static Expected<SectionFlagsUpdate> 251f75da0c8SAlexey Lapshin parseSetSectionFlagValue(StringRef FlagValue) { 252f75da0c8SAlexey Lapshin if (!StringRef(FlagValue).contains('=')) 253f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 254f75da0c8SAlexey Lapshin "bad format for --set-section-flags: missing '='"); 255f75da0c8SAlexey Lapshin 256f75da0c8SAlexey Lapshin // Initial split: ".foo" = "f1,f2,..." 257f75da0c8SAlexey Lapshin auto Section2Flags = StringRef(FlagValue).split('='); 258f75da0c8SAlexey Lapshin SectionFlagsUpdate SFU; 259f75da0c8SAlexey Lapshin SFU.Name = Section2Flags.first; 260f75da0c8SAlexey Lapshin 261f75da0c8SAlexey Lapshin // Flags split: "f1" "f2" ... 262f75da0c8SAlexey Lapshin SmallVector<StringRef, 6> SectionFlags; 263f75da0c8SAlexey Lapshin Section2Flags.second.split(SectionFlags, ','); 264f75da0c8SAlexey Lapshin Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags); 265f75da0c8SAlexey Lapshin if (!ParsedFlagSet) 266f75da0c8SAlexey Lapshin return ParsedFlagSet.takeError(); 267f75da0c8SAlexey Lapshin SFU.NewFlags = *ParsedFlagSet; 268f75da0c8SAlexey Lapshin 269f75da0c8SAlexey Lapshin return SFU; 270f75da0c8SAlexey Lapshin } 271f75da0c8SAlexey Lapshin 27207d8a457SIlia Kuklin static Expected<uint8_t> parseVisibilityType(StringRef VisType) { 27307d8a457SIlia Kuklin const uint8_t Invalid = 0xff; 27407d8a457SIlia Kuklin uint8_t type = StringSwitch<uint8_t>(VisType) 27507d8a457SIlia Kuklin .Case("default", ELF::STV_DEFAULT) 27607d8a457SIlia Kuklin .Case("hidden", ELF::STV_HIDDEN) 27707d8a457SIlia Kuklin .Case("internal", ELF::STV_INTERNAL) 27807d8a457SIlia Kuklin .Case("protected", ELF::STV_PROTECTED) 27907d8a457SIlia Kuklin .Default(Invalid); 28007d8a457SIlia Kuklin if (type == Invalid) 28107d8a457SIlia Kuklin return createStringError(errc::invalid_argument, 28207d8a457SIlia Kuklin "'%s' is not a valid symbol visibility", 28307d8a457SIlia Kuklin VisType.str().c_str()); 28407d8a457SIlia Kuklin return type; 28507d8a457SIlia Kuklin } 28607d8a457SIlia Kuklin 287f75da0c8SAlexey Lapshin namespace { 288f75da0c8SAlexey Lapshin struct TargetInfo { 289f75da0c8SAlexey Lapshin FileFormat Format; 290f75da0c8SAlexey Lapshin MachineInfo Machine; 291f75da0c8SAlexey Lapshin }; 292f75da0c8SAlexey Lapshin } // namespace 293f75da0c8SAlexey Lapshin 294f75da0c8SAlexey Lapshin // FIXME: consolidate with the bfd parsing used by lld. 295f75da0c8SAlexey Lapshin static const StringMap<MachineInfo> TargetMap{ 296f75da0c8SAlexey Lapshin // Name, {EMachine, 64bit, LittleEndian} 297f75da0c8SAlexey Lapshin // x86 298f75da0c8SAlexey Lapshin {"elf32-i386", {ELF::EM_386, false, true}}, 299f75da0c8SAlexey Lapshin {"elf32-x86-64", {ELF::EM_X86_64, false, true}}, 300f75da0c8SAlexey Lapshin {"elf64-x86-64", {ELF::EM_X86_64, true, true}}, 301f75da0c8SAlexey Lapshin // Intel MCU 302f75da0c8SAlexey Lapshin {"elf32-iamcu", {ELF::EM_IAMCU, false, true}}, 303f75da0c8SAlexey Lapshin // ARM 304f75da0c8SAlexey Lapshin {"elf32-littlearm", {ELF::EM_ARM, false, true}}, 305f75da0c8SAlexey Lapshin // ARM AArch64 306f75da0c8SAlexey Lapshin {"elf64-aarch64", {ELF::EM_AARCH64, true, true}}, 307f75da0c8SAlexey Lapshin {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}}, 308f75da0c8SAlexey Lapshin // RISC-V 309f75da0c8SAlexey Lapshin {"elf32-littleriscv", {ELF::EM_RISCV, false, true}}, 310f75da0c8SAlexey Lapshin {"elf64-littleriscv", {ELF::EM_RISCV, true, true}}, 311f75da0c8SAlexey Lapshin // PowerPC 312f75da0c8SAlexey Lapshin {"elf32-powerpc", {ELF::EM_PPC, false, false}}, 313f75da0c8SAlexey Lapshin {"elf32-powerpcle", {ELF::EM_PPC, false, true}}, 314f75da0c8SAlexey Lapshin {"elf64-powerpc", {ELF::EM_PPC64, true, false}}, 315f75da0c8SAlexey Lapshin {"elf64-powerpcle", {ELF::EM_PPC64, true, true}}, 316f75da0c8SAlexey Lapshin // MIPS 317f75da0c8SAlexey Lapshin {"elf32-bigmips", {ELF::EM_MIPS, false, false}}, 318f75da0c8SAlexey Lapshin {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}}, 319f75da0c8SAlexey Lapshin {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}}, 320f75da0c8SAlexey Lapshin {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}}, 321f75da0c8SAlexey Lapshin {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}}, 322f75da0c8SAlexey Lapshin {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}}, 323f75da0c8SAlexey Lapshin {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}}, 324f75da0c8SAlexey Lapshin // SPARC 325f75da0c8SAlexey Lapshin {"elf32-sparc", {ELF::EM_SPARC, false, false}}, 326f75da0c8SAlexey Lapshin {"elf32-sparcel", {ELF::EM_SPARC, false, true}}, 327441afb39SWANG Xuerui // Hexagon 328f75da0c8SAlexey Lapshin {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}}, 329441afb39SWANG Xuerui // LoongArch 330441afb39SWANG Xuerui {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}}, 331441afb39SWANG Xuerui {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}}, 3323c02cb74SUlrich Weigand // SystemZ 3333c02cb74SUlrich Weigand {"elf64-s390", {ELF::EM_S390, true, false}}, 334f75da0c8SAlexey Lapshin }; 335f75da0c8SAlexey Lapshin 336f75da0c8SAlexey Lapshin static Expected<TargetInfo> 337f75da0c8SAlexey Lapshin getOutputTargetInfoByTargetName(StringRef TargetName) { 338f75da0c8SAlexey Lapshin StringRef OriginalTargetName = TargetName; 339f75da0c8SAlexey Lapshin bool IsFreeBSD = TargetName.consume_back("-freebsd"); 340f75da0c8SAlexey Lapshin auto Iter = TargetMap.find(TargetName); 341f75da0c8SAlexey Lapshin if (Iter == std::end(TargetMap)) 342f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 343f75da0c8SAlexey Lapshin "invalid output format: '%s'", 344f75da0c8SAlexey Lapshin OriginalTargetName.str().c_str()); 345f75da0c8SAlexey Lapshin MachineInfo MI = Iter->getValue(); 346f75da0c8SAlexey Lapshin if (IsFreeBSD) 347f75da0c8SAlexey Lapshin MI.OSABI = ELF::ELFOSABI_FREEBSD; 348f75da0c8SAlexey Lapshin 349f75da0c8SAlexey Lapshin FileFormat Format; 350586ecdf2SKazu Hirata if (TargetName.starts_with("elf")) 351f75da0c8SAlexey Lapshin Format = FileFormat::ELF; 352f75da0c8SAlexey Lapshin else 353f75da0c8SAlexey Lapshin // This should never happen because `TargetName` is valid (it certainly 354f75da0c8SAlexey Lapshin // exists in the TargetMap). 355f75da0c8SAlexey Lapshin llvm_unreachable("unknown target prefix"); 356f75da0c8SAlexey Lapshin 357f75da0c8SAlexey Lapshin return {TargetInfo{Format, MI}}; 358f75da0c8SAlexey Lapshin } 359f75da0c8SAlexey Lapshin 360f75da0c8SAlexey Lapshin static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc, 361f75da0c8SAlexey Lapshin StringRef Filename, MatchStyle MS, 362f75da0c8SAlexey Lapshin function_ref<Error(Error)> ErrorCallback) { 363f75da0c8SAlexey Lapshin StringSaver Saver(Alloc); 364f75da0c8SAlexey Lapshin SmallVector<StringRef, 16> Lines; 365f75da0c8SAlexey Lapshin auto BufOrErr = MemoryBuffer::getFile(Filename); 366f75da0c8SAlexey Lapshin if (!BufOrErr) 367f75da0c8SAlexey Lapshin return createFileError(Filename, BufOrErr.getError()); 368f75da0c8SAlexey Lapshin 369f75da0c8SAlexey Lapshin BufOrErr.get()->getBuffer().split(Lines, '\n'); 370f75da0c8SAlexey Lapshin for (StringRef Line : Lines) { 371f75da0c8SAlexey Lapshin // Ignore everything after '#', trim whitespace, and only add the symbol if 372f75da0c8SAlexey Lapshin // it's not empty. 373f75da0c8SAlexey Lapshin auto TrimmedLine = Line.split('#').first.trim(); 374f75da0c8SAlexey Lapshin if (!TrimmedLine.empty()) 375f75da0c8SAlexey Lapshin if (Error E = Symbols.addMatcher(NameOrPattern::create( 376f75da0c8SAlexey Lapshin Saver.save(TrimmedLine), MS, ErrorCallback))) 377f75da0c8SAlexey Lapshin return E; 378f75da0c8SAlexey Lapshin } 379f75da0c8SAlexey Lapshin 380f75da0c8SAlexey Lapshin return Error::success(); 381f75da0c8SAlexey Lapshin } 382f75da0c8SAlexey Lapshin 383f75da0c8SAlexey Lapshin static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename, 384f75da0c8SAlexey Lapshin BumpPtrAllocator &Alloc, 385f75da0c8SAlexey Lapshin StringRef Filename) { 386f75da0c8SAlexey Lapshin StringSaver Saver(Alloc); 387f75da0c8SAlexey Lapshin SmallVector<StringRef, 16> Lines; 388f75da0c8SAlexey Lapshin auto BufOrErr = MemoryBuffer::getFile(Filename); 389f75da0c8SAlexey Lapshin if (!BufOrErr) 390f75da0c8SAlexey Lapshin return createFileError(Filename, BufOrErr.getError()); 391f75da0c8SAlexey Lapshin 392f75da0c8SAlexey Lapshin BufOrErr.get()->getBuffer().split(Lines, '\n'); 393f75da0c8SAlexey Lapshin size_t NumLines = Lines.size(); 394f75da0c8SAlexey Lapshin for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) { 395f75da0c8SAlexey Lapshin StringRef TrimmedLine = Lines[LineNo].split('#').first.trim(); 396f75da0c8SAlexey Lapshin if (TrimmedLine.empty()) 397f75da0c8SAlexey Lapshin continue; 398f75da0c8SAlexey Lapshin 399f75da0c8SAlexey Lapshin std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' '); 400f75da0c8SAlexey Lapshin StringRef NewName = Pair.second.trim(); 401f75da0c8SAlexey Lapshin if (NewName.empty()) 402f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 403f75da0c8SAlexey Lapshin "%s:%zu: missing new symbol name", 404f75da0c8SAlexey Lapshin Filename.str().c_str(), LineNo + 1); 405f75da0c8SAlexey Lapshin SymbolsToRename.insert({Pair.first, NewName}); 406f75da0c8SAlexey Lapshin } 407f75da0c8SAlexey Lapshin return Error::success(); 408f75da0c8SAlexey Lapshin } 409f75da0c8SAlexey Lapshin 410f75da0c8SAlexey Lapshin template <class T> static ErrorOr<T> getAsInteger(StringRef Val) { 411f75da0c8SAlexey Lapshin T Result; 412f75da0c8SAlexey Lapshin if (Val.getAsInteger(0, Result)) 413f75da0c8SAlexey Lapshin return errc::invalid_argument; 414f75da0c8SAlexey Lapshin return Result; 415f75da0c8SAlexey Lapshin } 416f75da0c8SAlexey Lapshin 417f75da0c8SAlexey Lapshin namespace { 418f75da0c8SAlexey Lapshin 419f75da0c8SAlexey Lapshin enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip }; 420f75da0c8SAlexey Lapshin 421f75da0c8SAlexey Lapshin } // anonymous namespace 422f75da0c8SAlexey Lapshin 423f75da0c8SAlexey Lapshin static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS, 424f75da0c8SAlexey Lapshin ToolType Tool) { 425f75da0c8SAlexey Lapshin StringRef HelpText, ToolName; 426f75da0c8SAlexey Lapshin switch (Tool) { 427f75da0c8SAlexey Lapshin case ToolType::Objcopy: 428f75da0c8SAlexey Lapshin ToolName = "llvm-objcopy"; 429f75da0c8SAlexey Lapshin HelpText = " [options] input [output]"; 430f75da0c8SAlexey Lapshin break; 431f75da0c8SAlexey Lapshin case ToolType::Strip: 432f75da0c8SAlexey Lapshin ToolName = "llvm-strip"; 433f75da0c8SAlexey Lapshin HelpText = " [options] inputs..."; 434f75da0c8SAlexey Lapshin break; 435f75da0c8SAlexey Lapshin case ToolType::InstallNameTool: 436f75da0c8SAlexey Lapshin ToolName = "llvm-install-name-tool"; 437f75da0c8SAlexey Lapshin HelpText = " [options] input"; 438f75da0c8SAlexey Lapshin break; 439f75da0c8SAlexey Lapshin case ToolType::BitcodeStrip: 440f75da0c8SAlexey Lapshin ToolName = "llvm-bitcode-strip"; 441f75da0c8SAlexey Lapshin HelpText = " [options] input"; 442f75da0c8SAlexey Lapshin break; 443f75da0c8SAlexey Lapshin } 444f75da0c8SAlexey Lapshin OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(), 445f75da0c8SAlexey Lapshin (ToolName + " tool").str().c_str()); 446f75da0c8SAlexey Lapshin // TODO: Replace this with libOption call once it adds extrahelp support. 447f75da0c8SAlexey Lapshin // The CommandLine library has a cl::extrahelp class to support this, 448f75da0c8SAlexey Lapshin // but libOption does not have that yet. 449f75da0c8SAlexey Lapshin OS << "\nPass @FILE as argument to read options from FILE.\n"; 450f75da0c8SAlexey Lapshin } 451f75da0c8SAlexey Lapshin 452f75da0c8SAlexey Lapshin static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) { 453f75da0c8SAlexey Lapshin // Parse value given with --add-symbol option and create the 454f75da0c8SAlexey Lapshin // new symbol if possible. The value format for --add-symbol is: 455f75da0c8SAlexey Lapshin // 456f75da0c8SAlexey Lapshin // <name>=[<section>:]<value>[,<flags>] 457f75da0c8SAlexey Lapshin // 458f75da0c8SAlexey Lapshin // where: 459f75da0c8SAlexey Lapshin // <name> - symbol name, can be empty string 460f75da0c8SAlexey Lapshin // <section> - optional section name. If not given ABS symbol is created 461f75da0c8SAlexey Lapshin // <value> - symbol value, can be decimal or hexadecimal number prefixed 462f75da0c8SAlexey Lapshin // with 0x. 463f75da0c8SAlexey Lapshin // <flags> - optional flags affecting symbol type, binding or visibility. 464f75da0c8SAlexey Lapshin NewSymbolInfo SI; 465f75da0c8SAlexey Lapshin StringRef Value; 466f75da0c8SAlexey Lapshin std::tie(SI.SymbolName, Value) = FlagValue.split('='); 467f75da0c8SAlexey Lapshin if (Value.empty()) 468f75da0c8SAlexey Lapshin return createStringError( 469f75da0c8SAlexey Lapshin errc::invalid_argument, 470f75da0c8SAlexey Lapshin "bad format for --add-symbol, missing '=' after '%s'", 471f75da0c8SAlexey Lapshin SI.SymbolName.str().c_str()); 472f75da0c8SAlexey Lapshin 473f75da0c8SAlexey Lapshin if (Value.contains(':')) { 474f75da0c8SAlexey Lapshin std::tie(SI.SectionName, Value) = Value.split(':'); 475f75da0c8SAlexey Lapshin if (SI.SectionName.empty() || Value.empty()) 476f75da0c8SAlexey Lapshin return createStringError( 477f75da0c8SAlexey Lapshin errc::invalid_argument, 478f75da0c8SAlexey Lapshin "bad format for --add-symbol, missing section name or symbol value"); 479f75da0c8SAlexey Lapshin } 480f75da0c8SAlexey Lapshin 481f75da0c8SAlexey Lapshin SmallVector<StringRef, 6> Flags; 482f75da0c8SAlexey Lapshin Value.split(Flags, ','); 483f75da0c8SAlexey Lapshin if (Flags[0].getAsInteger(0, SI.Value)) 484f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, "bad symbol value: '%s'", 485f75da0c8SAlexey Lapshin Flags[0].str().c_str()); 486f75da0c8SAlexey Lapshin 487f75da0c8SAlexey Lapshin using Functor = std::function<void()>; 488f75da0c8SAlexey Lapshin SmallVector<StringRef, 6> UnsupportedFlags; 489f75da0c8SAlexey Lapshin for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I) 490f75da0c8SAlexey Lapshin static_cast<Functor>( 491f75da0c8SAlexey Lapshin StringSwitch<Functor>(Flags[I]) 492f75da0c8SAlexey Lapshin .CaseLower("global", 493f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Global); }) 494f75da0c8SAlexey Lapshin .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); }) 495f75da0c8SAlexey Lapshin .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); }) 496f75da0c8SAlexey Lapshin .CaseLower("default", 497f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Default); }) 498f75da0c8SAlexey Lapshin .CaseLower("hidden", 499f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Hidden); }) 500f75da0c8SAlexey Lapshin .CaseLower("protected", 501f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Protected); }) 502f75da0c8SAlexey Lapshin .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); }) 503f75da0c8SAlexey Lapshin .CaseLower("section", 504f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Section); }) 505f75da0c8SAlexey Lapshin .CaseLower("object", 506f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Object); }) 507f75da0c8SAlexey Lapshin .CaseLower("function", 508f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Function); }) 509f75da0c8SAlexey Lapshin .CaseLower( 510f75da0c8SAlexey Lapshin "indirect-function", 511f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); }) 512f75da0c8SAlexey Lapshin .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); }) 513f75da0c8SAlexey Lapshin .CaseLower("constructor", 514f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Constructor); }) 515f75da0c8SAlexey Lapshin .CaseLower("warning", 516f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Warning); }) 517f75da0c8SAlexey Lapshin .CaseLower("indirect", 518f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Indirect); }) 519f75da0c8SAlexey Lapshin .CaseLower("synthetic", 520f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::Synthetic); }) 521f75da0c8SAlexey Lapshin .CaseLower("unique-object", 522f75da0c8SAlexey Lapshin [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); }) 523f75da0c8SAlexey Lapshin .StartsWithLower("before=", 524f75da0c8SAlexey Lapshin [&] { 525f75da0c8SAlexey Lapshin StringRef SymNamePart = 526f75da0c8SAlexey Lapshin Flags[I].split('=').second; 527f75da0c8SAlexey Lapshin 528f75da0c8SAlexey Lapshin if (!SymNamePart.empty()) 529f75da0c8SAlexey Lapshin SI.BeforeSyms.push_back(SymNamePart); 530f75da0c8SAlexey Lapshin }) 531f75da0c8SAlexey Lapshin .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))(); 532f75da0c8SAlexey Lapshin if (!UnsupportedFlags.empty()) 533f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 534f75da0c8SAlexey Lapshin "unsupported flag%s for --add-symbol: '%s'", 535f75da0c8SAlexey Lapshin UnsupportedFlags.size() > 1 ? "s" : "", 536f75da0c8SAlexey Lapshin join(UnsupportedFlags, "', '").c_str()); 537f75da0c8SAlexey Lapshin 538f75da0c8SAlexey Lapshin return SI; 539f75da0c8SAlexey Lapshin } 540f75da0c8SAlexey Lapshin 541*10772807SIgor Kudrin static Expected<RemoveNoteInfo> parseRemoveNoteInfo(StringRef FlagValue) { 542*10772807SIgor Kudrin // Parse value given with --remove-note option. The format is: 543*10772807SIgor Kudrin // 544*10772807SIgor Kudrin // [name/]type_id 545*10772807SIgor Kudrin // 546*10772807SIgor Kudrin // where: 547*10772807SIgor Kudrin // <name> - optional note name. If not given, all notes with the specified 548*10772807SIgor Kudrin // <type_id> are removed. 549*10772807SIgor Kudrin // <type_id> - note type value, can be decimal or hexadecimal number prefixed 550*10772807SIgor Kudrin // with 0x. 551*10772807SIgor Kudrin RemoveNoteInfo NI; 552*10772807SIgor Kudrin StringRef TypeIdStr; 553*10772807SIgor Kudrin if (auto Idx = FlagValue.find('/'); Idx != StringRef::npos) { 554*10772807SIgor Kudrin if (Idx == 0) 555*10772807SIgor Kudrin return createStringError( 556*10772807SIgor Kudrin errc::invalid_argument, 557*10772807SIgor Kudrin "bad format for --remove-note, note name is empty"); 558*10772807SIgor Kudrin NI.Name = FlagValue.slice(0, Idx); 559*10772807SIgor Kudrin TypeIdStr = FlagValue.substr(Idx + 1); 560*10772807SIgor Kudrin } else { 561*10772807SIgor Kudrin TypeIdStr = FlagValue; 562*10772807SIgor Kudrin } 563*10772807SIgor Kudrin if (TypeIdStr.empty()) 564*10772807SIgor Kudrin return createStringError(errc::invalid_argument, 565*10772807SIgor Kudrin "bad format for --remove-note, missing type_id"); 566*10772807SIgor Kudrin if (TypeIdStr.getAsInteger(0, NI.TypeId)) 567*10772807SIgor Kudrin return createStringError(errc::invalid_argument, 568*10772807SIgor Kudrin "bad note type_id for --remove-note: '%s'", 569*10772807SIgor Kudrin TypeIdStr.str().c_str()); 570*10772807SIgor Kudrin return NI; 571*10772807SIgor Kudrin } 572*10772807SIgor Kudrin 573a6f3fedcSAlexey Lapshin // Parse input option \p ArgValue and load section data. This function 574a6f3fedcSAlexey Lapshin // extracts section name and name of the file keeping section data from 575a6f3fedcSAlexey Lapshin // ArgValue, loads data from the file, and stores section name and data 576a6f3fedcSAlexey Lapshin // into the vector of new sections \p NewSections. 577a6f3fedcSAlexey Lapshin static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName, 57853613044SFangrui Song SmallVector<NewSectionInfo, 0> &NewSections) { 579a6f3fedcSAlexey Lapshin if (!ArgValue.contains('=')) 580a6f3fedcSAlexey Lapshin return createStringError(errc::invalid_argument, 581a6f3fedcSAlexey Lapshin "bad format for " + OptionName + ": missing '='"); 582a6f3fedcSAlexey Lapshin 583a6f3fedcSAlexey Lapshin std::pair<StringRef, StringRef> SecPair = ArgValue.split("="); 584a6f3fedcSAlexey Lapshin if (SecPair.second.empty()) 585a6f3fedcSAlexey Lapshin return createStringError(errc::invalid_argument, "bad format for " + 586a6f3fedcSAlexey Lapshin OptionName + 587a6f3fedcSAlexey Lapshin ": missing file name"); 588a6f3fedcSAlexey Lapshin 589a6f3fedcSAlexey Lapshin ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 590a6f3fedcSAlexey Lapshin MemoryBuffer::getFile(SecPair.second); 591a6f3fedcSAlexey Lapshin if (!BufOrErr) 592a6f3fedcSAlexey Lapshin return createFileError(SecPair.second, 593a6f3fedcSAlexey Lapshin errorCodeToError(BufOrErr.getError())); 594a6f3fedcSAlexey Lapshin 595a6f3fedcSAlexey Lapshin NewSections.push_back({SecPair.first, std::move(*BufOrErr)}); 596a6f3fedcSAlexey Lapshin return Error::success(); 597a6f3fedcSAlexey Lapshin } 598a6f3fedcSAlexey Lapshin 59933200363SEleanor Bonnici static Expected<int64_t> parseChangeSectionLMA(StringRef ArgValue, 60033200363SEleanor Bonnici StringRef OptionName) { 60133200363SEleanor Bonnici StringRef StringValue; 60233200363SEleanor Bonnici if (ArgValue.starts_with("*+")) { 60322e55ba3SKazu Hirata StringValue = ArgValue.substr(2); 60433200363SEleanor Bonnici } else if (ArgValue.starts_with("*-")) { 60522e55ba3SKazu Hirata StringValue = ArgValue.substr(1); 60633200363SEleanor Bonnici } else if (ArgValue.contains("=")) { 60733200363SEleanor Bonnici return createStringError(errc::invalid_argument, 60833200363SEleanor Bonnici "bad format for " + OptionName + 60933200363SEleanor Bonnici ": changing LMA to a specific value is not " 61033200363SEleanor Bonnici "supported. Use *+val or *-val instead"); 61133200363SEleanor Bonnici } else if (ArgValue.contains("+") || ArgValue.contains("-")) { 61233200363SEleanor Bonnici return createStringError(errc::invalid_argument, 61333200363SEleanor Bonnici "bad format for " + OptionName + 61433200363SEleanor Bonnici ": changing a specific section LMA is not " 61533200363SEleanor Bonnici "supported. Use *+val or *-val instead"); 61633200363SEleanor Bonnici } 61733200363SEleanor Bonnici if (StringValue.empty()) 61833200363SEleanor Bonnici return createStringError(errc::invalid_argument, 61933200363SEleanor Bonnici "bad format for " + OptionName + 62033200363SEleanor Bonnici ": missing LMA offset"); 62133200363SEleanor Bonnici 62233200363SEleanor Bonnici auto LMAValue = getAsInteger<int64_t>(StringValue); 62333200363SEleanor Bonnici if (!LMAValue) 62433200363SEleanor Bonnici return createStringError(LMAValue.getError(), 62533200363SEleanor Bonnici "bad format for " + OptionName + ": value after " + 62633200363SEleanor Bonnici ArgValue.slice(0, 2) + " is " + StringValue + 62733200363SEleanor Bonnici " when it should be an integer"); 62833200363SEleanor Bonnici return *LMAValue; 62933200363SEleanor Bonnici } 63033200363SEleanor Bonnici 6312b2f4ae0SEleanor Bonnici static Expected<SectionPatternAddressUpdate> 6322b2f4ae0SEleanor Bonnici parseChangeSectionAddr(StringRef ArgValue, StringRef OptionName, 6332b2f4ae0SEleanor Bonnici MatchStyle SectionMatchStyle, 6342b2f4ae0SEleanor Bonnici function_ref<Error(Error)> ErrorCallback) { 6352b2f4ae0SEleanor Bonnici SectionPatternAddressUpdate PatternUpdate; 6362b2f4ae0SEleanor Bonnici 6372b2f4ae0SEleanor Bonnici size_t LastSymbolIndex = ArgValue.find_last_of("+-="); 6382b2f4ae0SEleanor Bonnici if (LastSymbolIndex == StringRef::npos) 6392b2f4ae0SEleanor Bonnici return createStringError(errc::invalid_argument, 6402b2f4ae0SEleanor Bonnici "bad format for " + OptionName + 6412b2f4ae0SEleanor Bonnici ": argument value " + ArgValue + 6422b2f4ae0SEleanor Bonnici " is invalid. See --help"); 6432b2f4ae0SEleanor Bonnici char UpdateSymbol = ArgValue[LastSymbolIndex]; 6442b2f4ae0SEleanor Bonnici 6452b2f4ae0SEleanor Bonnici StringRef SectionPattern = ArgValue.slice(0, LastSymbolIndex); 6462b2f4ae0SEleanor Bonnici if (SectionPattern.empty()) 6472b2f4ae0SEleanor Bonnici return createStringError( 6482b2f4ae0SEleanor Bonnici errc::invalid_argument, 6492b2f4ae0SEleanor Bonnici "bad format for " + OptionName + 6502b2f4ae0SEleanor Bonnici ": missing section pattern to apply address change to"); 6512b2f4ae0SEleanor Bonnici if (Error E = PatternUpdate.SectionPattern.addMatcher(NameOrPattern::create( 6522b2f4ae0SEleanor Bonnici SectionPattern, SectionMatchStyle, ErrorCallback))) 6532b2f4ae0SEleanor Bonnici return std::move(E); 6542b2f4ae0SEleanor Bonnici 65522e55ba3SKazu Hirata StringRef Value = ArgValue.substr(LastSymbolIndex + 1); 6562b2f4ae0SEleanor Bonnici if (Value.empty()) { 6572b2f4ae0SEleanor Bonnici switch (UpdateSymbol) { 6582b2f4ae0SEleanor Bonnici case '+': 6592b2f4ae0SEleanor Bonnici case '-': 6602b2f4ae0SEleanor Bonnici return createStringError(errc::invalid_argument, 6612b2f4ae0SEleanor Bonnici "bad format for " + OptionName + 6622b2f4ae0SEleanor Bonnici ": missing value of offset after '" + 6632b2f4ae0SEleanor Bonnici std::string({UpdateSymbol}) + "'"); 6642b2f4ae0SEleanor Bonnici 6652b2f4ae0SEleanor Bonnici case '=': 6662b2f4ae0SEleanor Bonnici return createStringError(errc::invalid_argument, 6672b2f4ae0SEleanor Bonnici "bad format for " + OptionName + 6682b2f4ae0SEleanor Bonnici ": missing address value after '='"); 6692b2f4ae0SEleanor Bonnici } 6702b2f4ae0SEleanor Bonnici } 6712b2f4ae0SEleanor Bonnici auto AddrValue = getAsInteger<uint64_t>(Value); 6722b2f4ae0SEleanor Bonnici if (!AddrValue) 6732b2f4ae0SEleanor Bonnici return createStringError(AddrValue.getError(), 6742b2f4ae0SEleanor Bonnici "bad format for " + OptionName + ": value after " + 6752b2f4ae0SEleanor Bonnici std::string({UpdateSymbol}) + " is " + Value + 6762b2f4ae0SEleanor Bonnici " when it should be a 64-bit integer"); 6772b2f4ae0SEleanor Bonnici 6782b2f4ae0SEleanor Bonnici switch (UpdateSymbol) { 6792b2f4ae0SEleanor Bonnici case '+': 6802b2f4ae0SEleanor Bonnici PatternUpdate.Update.Kind = AdjustKind::Add; 6812b2f4ae0SEleanor Bonnici break; 6822b2f4ae0SEleanor Bonnici case '-': 6832b2f4ae0SEleanor Bonnici PatternUpdate.Update.Kind = AdjustKind::Subtract; 6842b2f4ae0SEleanor Bonnici break; 6852b2f4ae0SEleanor Bonnici case '=': 6862b2f4ae0SEleanor Bonnici PatternUpdate.Update.Kind = AdjustKind::Set; 6872b2f4ae0SEleanor Bonnici } 6882b2f4ae0SEleanor Bonnici 6892b2f4ae0SEleanor Bonnici PatternUpdate.Update.Value = *AddrValue; 6902b2f4ae0SEleanor Bonnici return PatternUpdate; 6912b2f4ae0SEleanor Bonnici } 6922b2f4ae0SEleanor Bonnici 693a91c77eeSNico Weber // parseObjcopyOptions returns the config and sets the input arguments. If a 694a91c77eeSNico Weber // help flag is set then parseObjcopyOptions will print the help messege and 695f75da0c8SAlexey Lapshin // exit. 696f75da0c8SAlexey Lapshin Expected<DriverConfig> 6972444b6f0SFangrui Song objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr, 698f75da0c8SAlexey Lapshin function_ref<Error(Error)> ErrorCallback) { 699f75da0c8SAlexey Lapshin DriverConfig DC; 700f75da0c8SAlexey Lapshin ObjcopyOptTable T; 701f75da0c8SAlexey Lapshin 702f75da0c8SAlexey Lapshin unsigned MissingArgumentIndex, MissingArgumentCount; 703f75da0c8SAlexey Lapshin llvm::opt::InputArgList InputArgs = 704f75da0c8SAlexey Lapshin T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 705f75da0c8SAlexey Lapshin 706183beb33SAlexey Karyakin if (MissingArgumentCount) 707183beb33SAlexey Karyakin return createStringError( 708183beb33SAlexey Karyakin errc::invalid_argument, 709183beb33SAlexey Karyakin "argument to '%s' is missing (expected %d value(s))", 710183beb33SAlexey Karyakin InputArgs.getArgString(MissingArgumentIndex), MissingArgumentCount); 711183beb33SAlexey Karyakin 7122444b6f0SFangrui Song if (InputArgs.size() == 0) { 713f75da0c8SAlexey Lapshin printHelp(T, errs(), ToolType::Objcopy); 714f75da0c8SAlexey Lapshin exit(1); 715f75da0c8SAlexey Lapshin } 716f75da0c8SAlexey Lapshin 717f75da0c8SAlexey Lapshin if (InputArgs.hasArg(OBJCOPY_help)) { 718f75da0c8SAlexey Lapshin printHelp(T, outs(), ToolType::Objcopy); 719f75da0c8SAlexey Lapshin exit(0); 720f75da0c8SAlexey Lapshin } 721f75da0c8SAlexey Lapshin 722f75da0c8SAlexey Lapshin if (InputArgs.hasArg(OBJCOPY_version)) { 723f75da0c8SAlexey Lapshin outs() << "llvm-objcopy, compatible with GNU objcopy\n"; 724f75da0c8SAlexey Lapshin cl::PrintVersionMessage(); 725f75da0c8SAlexey Lapshin exit(0); 726f75da0c8SAlexey Lapshin } 727f75da0c8SAlexey Lapshin 728f75da0c8SAlexey Lapshin SmallVector<const char *, 2> Positional; 729f75da0c8SAlexey Lapshin 73086e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN)) 731f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, "unknown argument '%s'", 732f75da0c8SAlexey Lapshin Arg->getAsString(InputArgs).c_str()); 733f75da0c8SAlexey Lapshin 73486e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT)) 735f75da0c8SAlexey Lapshin Positional.push_back(Arg->getValue()); 736f75da0c8SAlexey Lapshin 737f75da0c8SAlexey Lapshin if (Positional.empty()) 738f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, "no input file specified"); 739f75da0c8SAlexey Lapshin 740f75da0c8SAlexey Lapshin if (Positional.size() > 2) 741f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 742f75da0c8SAlexey Lapshin "too many positional arguments"); 743f75da0c8SAlexey Lapshin 744f75da0c8SAlexey Lapshin ConfigManager ConfigMgr; 745f75da0c8SAlexey Lapshin CommonConfig &Config = ConfigMgr.Common; 746f75da0c8SAlexey Lapshin COFFConfig &COFFConfig = ConfigMgr.COFF; 747f75da0c8SAlexey Lapshin ELFConfig &ELFConfig = ConfigMgr.ELF; 748f75da0c8SAlexey Lapshin MachOConfig &MachOConfig = ConfigMgr.MachO; 749f75da0c8SAlexey Lapshin Config.InputFilename = Positional[0]; 750f75da0c8SAlexey Lapshin Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1]; 751f75da0c8SAlexey Lapshin if (InputArgs.hasArg(OBJCOPY_target) && 752f75da0c8SAlexey Lapshin (InputArgs.hasArg(OBJCOPY_input_target) || 753f75da0c8SAlexey Lapshin InputArgs.hasArg(OBJCOPY_output_target))) 754f75da0c8SAlexey Lapshin return createStringError( 755f75da0c8SAlexey Lapshin errc::invalid_argument, 756f75da0c8SAlexey Lapshin "--target cannot be used with --input-target or --output-target"); 757f75da0c8SAlexey Lapshin 758f75da0c8SAlexey Lapshin if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard)) 759f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 760f75da0c8SAlexey Lapshin "--regex and --wildcard are incompatible"); 761f75da0c8SAlexey Lapshin 762f75da0c8SAlexey Lapshin MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex) 763f75da0c8SAlexey Lapshin ? MatchStyle::Regex 764f75da0c8SAlexey Lapshin : MatchStyle::Wildcard; 765f75da0c8SAlexey Lapshin MatchStyle SymbolMatchStyle 766f75da0c8SAlexey Lapshin = InputArgs.hasArg(OBJCOPY_regex) ? MatchStyle::Regex 767f75da0c8SAlexey Lapshin : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard 768f75da0c8SAlexey Lapshin : MatchStyle::Literal; 769f75da0c8SAlexey Lapshin StringRef InputFormat, OutputFormat; 770f75da0c8SAlexey Lapshin if (InputArgs.hasArg(OBJCOPY_target)) { 771f75da0c8SAlexey Lapshin InputFormat = InputArgs.getLastArgValue(OBJCOPY_target); 772f75da0c8SAlexey Lapshin OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target); 773f75da0c8SAlexey Lapshin } else { 774f75da0c8SAlexey Lapshin InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target); 775f75da0c8SAlexey Lapshin OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target); 776f75da0c8SAlexey Lapshin } 777f75da0c8SAlexey Lapshin 778f75da0c8SAlexey Lapshin // FIXME: Currently, we ignore the target for non-binary/ihex formats 779f75da0c8SAlexey Lapshin // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the 780f75da0c8SAlexey Lapshin // format by llvm::object::createBinary regardless of the option value. 781f75da0c8SAlexey Lapshin Config.InputFormat = StringSwitch<FileFormat>(InputFormat) 782f75da0c8SAlexey Lapshin .Case("binary", FileFormat::Binary) 783f75da0c8SAlexey Lapshin .Case("ihex", FileFormat::IHex) 784f75da0c8SAlexey Lapshin .Default(FileFormat::Unspecified); 785f75da0c8SAlexey Lapshin 786f75da0c8SAlexey Lapshin if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) { 787f75da0c8SAlexey Lapshin const uint8_t Invalid = 0xff; 788f75da0c8SAlexey Lapshin StringRef VisibilityStr = 789f75da0c8SAlexey Lapshin InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility); 790f75da0c8SAlexey Lapshin 791f75da0c8SAlexey Lapshin ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr) 792f75da0c8SAlexey Lapshin .Case("default", ELF::STV_DEFAULT) 793f75da0c8SAlexey Lapshin .Case("hidden", ELF::STV_HIDDEN) 794f75da0c8SAlexey Lapshin .Case("internal", ELF::STV_INTERNAL) 795f75da0c8SAlexey Lapshin .Case("protected", ELF::STV_PROTECTED) 796f75da0c8SAlexey Lapshin .Default(Invalid); 797f75da0c8SAlexey Lapshin 798f75da0c8SAlexey Lapshin if (ELFConfig.NewSymbolVisibility == Invalid) 799f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 800f75da0c8SAlexey Lapshin "'%s' is not a valid symbol visibility", 801f75da0c8SAlexey Lapshin VisibilityStr.str().c_str()); 802f75da0c8SAlexey Lapshin } 803f75da0c8SAlexey Lapshin 804f75da0c8SAlexey Lapshin for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) { 805f75da0c8SAlexey Lapshin StringRef Subsystem, Version; 806f75da0c8SAlexey Lapshin std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':'); 807f75da0c8SAlexey Lapshin COFFConfig.Subsystem = 808f75da0c8SAlexey Lapshin StringSwitch<unsigned>(Subsystem.lower()) 809f75da0c8SAlexey Lapshin .Case("boot_application", 810f75da0c8SAlexey Lapshin COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) 811f75da0c8SAlexey Lapshin .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI) 8126aefa918SVictor Campos .Cases("efi_application", "efi-app", 8136aefa918SVictor Campos COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION) 8146aefa918SVictor Campos .Cases("efi_boot_service_driver", "efi-bsd", 815f75da0c8SAlexey Lapshin COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) 816f75da0c8SAlexey Lapshin .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM) 8176aefa918SVictor Campos .Cases("efi_runtime_driver", "efi-rtd", 818f75da0c8SAlexey Lapshin COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) 819f75da0c8SAlexey Lapshin .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE) 820f75da0c8SAlexey Lapshin .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI) 821f75da0c8SAlexey Lapshin .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI) 822f75da0c8SAlexey Lapshin .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN); 823f75da0c8SAlexey Lapshin if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN) 824f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 825f75da0c8SAlexey Lapshin "'%s' is not a valid subsystem", 826f75da0c8SAlexey Lapshin Subsystem.str().c_str()); 827f75da0c8SAlexey Lapshin if (!Version.empty()) { 828f75da0c8SAlexey Lapshin StringRef Major, Minor; 829f75da0c8SAlexey Lapshin std::tie(Major, Minor) = Version.split('.'); 830f75da0c8SAlexey Lapshin unsigned Number; 831f75da0c8SAlexey Lapshin if (Major.getAsInteger(10, Number)) 832f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 833f75da0c8SAlexey Lapshin "'%s' is not a valid subsystem major version", 834f75da0c8SAlexey Lapshin Major.str().c_str()); 835f75da0c8SAlexey Lapshin COFFConfig.MajorSubsystemVersion = Number; 836f75da0c8SAlexey Lapshin Number = 0; 837f75da0c8SAlexey Lapshin if (!Minor.empty() && Minor.getAsInteger(10, Number)) 838f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 839f75da0c8SAlexey Lapshin "'%s' is not a valid subsystem minor version", 840f75da0c8SAlexey Lapshin Minor.str().c_str()); 841f75da0c8SAlexey Lapshin COFFConfig.MinorSubsystemVersion = Number; 842f75da0c8SAlexey Lapshin } 843f75da0c8SAlexey Lapshin } 844f75da0c8SAlexey Lapshin 845f75da0c8SAlexey Lapshin Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat) 846f75da0c8SAlexey Lapshin .Case("binary", FileFormat::Binary) 847f75da0c8SAlexey Lapshin .Case("ihex", FileFormat::IHex) 8487ddc3205Squic-areg .Case("srec", FileFormat::SREC) 849f75da0c8SAlexey Lapshin .Default(FileFormat::Unspecified); 850f75da0c8SAlexey Lapshin if (Config.OutputFormat == FileFormat::Unspecified) { 851f75da0c8SAlexey Lapshin if (OutputFormat.empty()) { 852f75da0c8SAlexey Lapshin Config.OutputFormat = Config.InputFormat; 853f75da0c8SAlexey Lapshin } else { 854f75da0c8SAlexey Lapshin Expected<TargetInfo> Target = 855f75da0c8SAlexey Lapshin getOutputTargetInfoByTargetName(OutputFormat); 856f75da0c8SAlexey Lapshin if (!Target) 857f75da0c8SAlexey Lapshin return Target.takeError(); 858f75da0c8SAlexey Lapshin Config.OutputFormat = Target->Format; 859f75da0c8SAlexey Lapshin Config.OutputArch = Target->Machine; 860f75da0c8SAlexey Lapshin } 861f75da0c8SAlexey Lapshin } 862f75da0c8SAlexey Lapshin 863ef03f662SFangrui Song if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) { 864ef03f662SFangrui Song Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue()) 865781dea02SFangrui Song .Case("zlib", DebugCompressionType::Zlib) 866b6e1fd76SFangrui Song .Case("zstd", DebugCompressionType::Zstd) 867f75da0c8SAlexey Lapshin .Default(DebugCompressionType::None); 868b6e1fd76SFangrui Song if (Config.CompressionType == DebugCompressionType::None) { 869f75da0c8SAlexey Lapshin return createStringError( 870f75da0c8SAlexey Lapshin errc::invalid_argument, 871f75da0c8SAlexey Lapshin "invalid or unsupported --compress-debug-sections format: %s", 872ef03f662SFangrui Song A->getValue()); 873b6e1fd76SFangrui Song } 874b6e1fd76SFangrui Song if (const char *Reason = compression::getReasonIfUnsupported( 875b6e1fd76SFangrui Song compression::formatFor(Config.CompressionType))) 876b6e1fd76SFangrui Song return createStringError(errc::invalid_argument, Reason); 877f75da0c8SAlexey Lapshin } 878f75da0c8SAlexey Lapshin 87907942987SFangrui Song for (const auto *A : InputArgs.filtered(OBJCOPY_compress_sections)) { 88007942987SFangrui Song SmallVector<StringRef, 0> Fields; 88107942987SFangrui Song StringRef(A->getValue()).split(Fields, '='); 88207942987SFangrui Song if (Fields.size() != 2 || Fields[1].empty()) { 88307942987SFangrui Song return createStringError( 88407942987SFangrui Song errc::invalid_argument, 88507942987SFangrui Song A->getSpelling() + 88607942987SFangrui Song ": parse error, not 'section-glob=[none|zlib|zstd]'"); 88707942987SFangrui Song } 88807942987SFangrui Song 88907942987SFangrui Song auto Type = StringSwitch<DebugCompressionType>(Fields[1]) 89007942987SFangrui Song .Case("zlib", DebugCompressionType::Zlib) 89107942987SFangrui Song .Case("zstd", DebugCompressionType::Zstd) 89207942987SFangrui Song .Default(DebugCompressionType::None); 89307942987SFangrui Song if (Type == DebugCompressionType::None && Fields[1] != "none") { 89407942987SFangrui Song return createStringError( 89507942987SFangrui Song errc::invalid_argument, 89607942987SFangrui Song "invalid or unsupported --compress-sections format: %s", 89707942987SFangrui Song A->getValue()); 89807942987SFangrui Song } 89907942987SFangrui Song 90007942987SFangrui Song auto &P = Config.compressSections.emplace_back(); 90107942987SFangrui Song P.second = Type; 90207942987SFangrui Song auto Matcher = 90307942987SFangrui Song NameOrPattern::create(Fields[0], SectionMatchStyle, ErrorCallback); 90407942987SFangrui Song // =none allows overriding a previous =zlib or =zstd. Reject negative 90507942987SFangrui Song // patterns, which would be confusing. 90607942987SFangrui Song if (Matcher && !Matcher->isPositiveMatch()) { 90707942987SFangrui Song return createStringError( 90807942987SFangrui Song errc::invalid_argument, 90907942987SFangrui Song "--compress-sections: negative pattern is unsupported"); 91007942987SFangrui Song } 91107942987SFangrui Song if (Error E = P.first.addMatcher(std::move(Matcher))) 91207942987SFangrui Song return std::move(E); 91307942987SFangrui Song } 91407942987SFangrui Song 915f75da0c8SAlexey Lapshin Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); 916f75da0c8SAlexey Lapshin // The gnu_debuglink's target is expected to not change or else its CRC would 917f75da0c8SAlexey Lapshin // become invalidated and get rejected. We can avoid recalculating the 918f75da0c8SAlexey Lapshin // checksum for every target file inside an archive by precomputing the CRC 919f75da0c8SAlexey Lapshin // here. This prevents a significant amount of I/O. 920f75da0c8SAlexey Lapshin if (!Config.AddGnuDebugLink.empty()) { 921f75da0c8SAlexey Lapshin auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink); 922f75da0c8SAlexey Lapshin if (!DebugOrErr) 923f75da0c8SAlexey Lapshin return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError()); 924f75da0c8SAlexey Lapshin auto Debug = std::move(*DebugOrErr); 925f75da0c8SAlexey Lapshin Config.GnuDebugLinkCRC32 = 926f75da0c8SAlexey Lapshin llvm::crc32(arrayRefFromStringRef(Debug->getBuffer())); 927f75da0c8SAlexey Lapshin } 928f75da0c8SAlexey Lapshin Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); 9291b87ebceSYi Kong 930f75da0c8SAlexey Lapshin Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols); 9311b87ebceSYi Kong Config.SymbolsPrefixRemove = 9321b87ebceSYi Kong InputArgs.getLastArgValue(OBJCOPY_remove_symbol_prefix); 9331b87ebceSYi Kong 934f75da0c8SAlexey Lapshin Config.AllocSectionsPrefix = 935f75da0c8SAlexey Lapshin InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections); 936f75da0c8SAlexey Lapshin if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition)) 937f75da0c8SAlexey Lapshin Config.ExtractPartition = Arg->getValue(); 938f75da0c8SAlexey Lapshin 9394070dffdSquic-akaryaki if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) { 9404070dffdSquic-akaryaki if (Config.OutputFormat != FileFormat::Binary) 9414070dffdSquic-akaryaki return createStringError( 9424070dffdSquic-akaryaki errc::invalid_argument, 9434070dffdSquic-akaryaki "'--gap-fill' is only supported for binary output"); 9444070dffdSquic-akaryaki ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue()); 9454070dffdSquic-akaryaki if (!Val) 9464070dffdSquic-akaryaki return createStringError(Val.getError(), "--gap-fill: bad number: %s", 9474070dffdSquic-akaryaki A->getValue()); 9484070dffdSquic-akaryaki uint8_t ByteVal = Val.get(); 9494070dffdSquic-akaryaki if (ByteVal != Val.get()) 9504070dffdSquic-akaryaki return createStringError(std::errc::value_too_large, 9514070dffdSquic-akaryaki "gap-fill value %s is out of range (0 to 0xff)", 9524070dffdSquic-akaryaki A->getValue()); 9534070dffdSquic-akaryaki Config.GapFill = ByteVal; 9544070dffdSquic-akaryaki } 9554070dffdSquic-akaryaki 9564070dffdSquic-akaryaki if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) { 9574070dffdSquic-akaryaki if (Config.OutputFormat != FileFormat::Binary) 9584070dffdSquic-akaryaki return createStringError( 9594070dffdSquic-akaryaki errc::invalid_argument, 9604070dffdSquic-akaryaki "'--pad-to' is only supported for binary output"); 9614070dffdSquic-akaryaki ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue()); 9624070dffdSquic-akaryaki if (!Addr) 9634070dffdSquic-akaryaki return createStringError(Addr.getError(), "--pad-to: bad number: %s", 9644070dffdSquic-akaryaki A->getValue()); 9654070dffdSquic-akaryaki Config.PadTo = *Addr; 9664070dffdSquic-akaryaki } 9674070dffdSquic-akaryaki 96833200363SEleanor Bonnici if (const auto *Arg = InputArgs.getLastArg(OBJCOPY_change_section_lma)) { 96933200363SEleanor Bonnici Expected<int64_t> LMAValue = 97033200363SEleanor Bonnici parseChangeSectionLMA(Arg->getValue(), Arg->getSpelling()); 97133200363SEleanor Bonnici if (!LMAValue) 97233200363SEleanor Bonnici return LMAValue.takeError(); 97333200363SEleanor Bonnici Config.ChangeSectionLMAValAll = *LMAValue; 97433200363SEleanor Bonnici } 97533200363SEleanor Bonnici 9762b2f4ae0SEleanor Bonnici for (auto *Arg : InputArgs.filtered(OBJCOPY_change_section_address)) { 9772b2f4ae0SEleanor Bonnici Expected<SectionPatternAddressUpdate> AddressUpdate = 9782b2f4ae0SEleanor Bonnici parseChangeSectionAddr(Arg->getValue(), Arg->getSpelling(), 9792b2f4ae0SEleanor Bonnici SectionMatchStyle, ErrorCallback); 9802b2f4ae0SEleanor Bonnici if (!AddressUpdate) 9812b2f4ae0SEleanor Bonnici return AddressUpdate.takeError(); 9822b2f4ae0SEleanor Bonnici Config.ChangeSectionAddress.push_back(*AddressUpdate); 9832b2f4ae0SEleanor Bonnici } 9842b2f4ae0SEleanor Bonnici 98586e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) { 986f75da0c8SAlexey Lapshin if (!StringRef(Arg->getValue()).contains('=')) 987f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 988f75da0c8SAlexey Lapshin "bad format for --redefine-sym"); 989f75da0c8SAlexey Lapshin auto Old2New = StringRef(Arg->getValue()).split('='); 990f75da0c8SAlexey Lapshin if (!Config.SymbolsToRename.insert(Old2New).second) 991f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 992f75da0c8SAlexey Lapshin "multiple redefinition of symbol '%s'", 993f75da0c8SAlexey Lapshin Old2New.first.str().c_str()); 994f75da0c8SAlexey Lapshin } 995f75da0c8SAlexey Lapshin 99686e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols)) 997f75da0c8SAlexey Lapshin if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc, 998f75da0c8SAlexey Lapshin Arg->getValue())) 999f75da0c8SAlexey Lapshin return std::move(E); 1000f75da0c8SAlexey Lapshin 100186e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) { 1002f75da0c8SAlexey Lapshin Expected<SectionRename> SR = 1003f75da0c8SAlexey Lapshin parseRenameSectionValue(StringRef(Arg->getValue())); 1004f75da0c8SAlexey Lapshin if (!SR) 1005f75da0c8SAlexey Lapshin return SR.takeError(); 1006f75da0c8SAlexey Lapshin if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second) 1007f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1008f75da0c8SAlexey Lapshin "multiple renames of section '%s'", 1009f75da0c8SAlexey Lapshin SR->OriginalName.str().c_str()); 1010f75da0c8SAlexey Lapshin } 101186e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) { 1012f75da0c8SAlexey Lapshin Expected<std::pair<StringRef, uint64_t>> NameAndAlign = 1013b28412d5SFangrui Song parseSetSectionAttribute("--set-section-alignment", Arg->getValue()); 1014f75da0c8SAlexey Lapshin if (!NameAndAlign) 1015f75da0c8SAlexey Lapshin return NameAndAlign.takeError(); 1016f75da0c8SAlexey Lapshin Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second; 1017f75da0c8SAlexey Lapshin } 101886e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) { 1019f75da0c8SAlexey Lapshin Expected<SectionFlagsUpdate> SFU = 1020f75da0c8SAlexey Lapshin parseSetSectionFlagValue(Arg->getValue()); 1021f75da0c8SAlexey Lapshin if (!SFU) 1022f75da0c8SAlexey Lapshin return SFU.takeError(); 1023f75da0c8SAlexey Lapshin if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second) 1024f75da0c8SAlexey Lapshin return createStringError( 1025f75da0c8SAlexey Lapshin errc::invalid_argument, 1026f75da0c8SAlexey Lapshin "--set-section-flags set multiple times for section '%s'", 1027f75da0c8SAlexey Lapshin SFU->Name.str().c_str()); 1028f75da0c8SAlexey Lapshin } 102986e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) { 1030b28412d5SFangrui Song Expected<std::pair<StringRef, uint64_t>> NameAndType = 1031b28412d5SFangrui Song parseSetSectionAttribute("--set-section-type", Arg->getValue()); 1032b28412d5SFangrui Song if (!NameAndType) 1033b28412d5SFangrui Song return NameAndType.takeError(); 1034b28412d5SFangrui Song Config.SetSectionType[NameAndType->first] = NameAndType->second; 1035b28412d5SFangrui Song } 1036b28412d5SFangrui Song // Prohibit combinations of --set-section-{flags,type} when the section name 1037b28412d5SFangrui Song // is used as the destination of a --rename-section. 1038f75da0c8SAlexey Lapshin for (const auto &E : Config.SectionsToRename) { 1039f75da0c8SAlexey Lapshin const SectionRename &SR = E.second; 1040b28412d5SFangrui Song auto Err = [&](const char *Option) { 1041f75da0c8SAlexey Lapshin return createStringError( 1042f75da0c8SAlexey Lapshin errc::invalid_argument, 1043b28412d5SFangrui Song "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option, 1044f75da0c8SAlexey Lapshin SR.NewName.str().c_str(), SR.OriginalName.str().c_str(), 1045f75da0c8SAlexey Lapshin SR.NewName.str().c_str()); 1046b28412d5SFangrui Song }; 1047b28412d5SFangrui Song if (Config.SetSectionFlags.count(SR.NewName)) 1048b28412d5SFangrui Song return Err("flags"); 1049b28412d5SFangrui Song if (Config.SetSectionType.count(SR.NewName)) 1050b28412d5SFangrui Song return Err("type"); 1051f75da0c8SAlexey Lapshin } 1052f75da0c8SAlexey Lapshin 105386e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section)) 1054f75da0c8SAlexey Lapshin if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( 1055f75da0c8SAlexey Lapshin Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1056f75da0c8SAlexey Lapshin return std::move(E); 105786e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section)) 1058f75da0c8SAlexey Lapshin if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( 1059f75da0c8SAlexey Lapshin Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1060f75da0c8SAlexey Lapshin return std::move(E); 106186e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section)) 1062f75da0c8SAlexey Lapshin if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create( 1063f75da0c8SAlexey Lapshin Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1064f75da0c8SAlexey Lapshin return std::move(E); 106586e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) { 1066a6f3fedcSAlexey Lapshin if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section", 1067a6f3fedcSAlexey Lapshin Config.AddSection)) 1068a6f3fedcSAlexey Lapshin return std::move(Err); 1069f75da0c8SAlexey Lapshin } 107086e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) { 1071a6f3fedcSAlexey Lapshin if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section", 1072a6f3fedcSAlexey Lapshin Config.UpdateSection)) 1073a6f3fedcSAlexey Lapshin return std::move(Err); 1074f75da0c8SAlexey Lapshin } 1075f75da0c8SAlexey Lapshin for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) { 1076f75da0c8SAlexey Lapshin StringRef Value(Arg->getValue()); 1077f75da0c8SAlexey Lapshin if (Value.split('=').second.empty()) 1078f75da0c8SAlexey Lapshin return createStringError( 1079f75da0c8SAlexey Lapshin errc::invalid_argument, 1080f75da0c8SAlexey Lapshin "bad format for --dump-section, expected section=file"); 1081f75da0c8SAlexey Lapshin Config.DumpSection.push_back(Value); 1082f75da0c8SAlexey Lapshin } 1083f75da0c8SAlexey Lapshin Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all); 1084f75da0c8SAlexey Lapshin Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu); 1085f75da0c8SAlexey Lapshin Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug); 1086f75da0c8SAlexey Lapshin Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo); 1087f75da0c8SAlexey Lapshin Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections); 1088f75da0c8SAlexey Lapshin Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc); 1089f75da0c8SAlexey Lapshin Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded); 1090f75da0c8SAlexey Lapshin Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo); 1091f75da0c8SAlexey Lapshin Config.ExtractMainPartition = 1092f75da0c8SAlexey Lapshin InputArgs.hasArg(OBJCOPY_extract_main_partition); 1093f75da0c8SAlexey Lapshin ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden); 1094f75da0c8SAlexey Lapshin Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken); 1095c37accf0SFangrui Song if (auto *Arg = 1096c37accf0SFangrui Song InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) { 1097c37accf0SFangrui Song Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all) 1098f75da0c8SAlexey Lapshin ? DiscardType::All 1099f75da0c8SAlexey Lapshin : DiscardType::Locals; 1100c37accf0SFangrui Song } 1101fb5a38bbSserge-sans-paille 1102fb5a38bbSserge-sans-paille ELFConfig.VerifyNoteSections = InputArgs.hasFlag( 1103fb5a38bbSserge-sans-paille OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true); 1104fb5a38bbSserge-sans-paille 1105f75da0c8SAlexey Lapshin Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug); 1106f75da0c8SAlexey Lapshin ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols); 1107f75da0c8SAlexey Lapshin MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined); 1108f75da0c8SAlexey Lapshin Config.DecompressDebugSections = 1109f75da0c8SAlexey Lapshin InputArgs.hasArg(OBJCOPY_decompress_debug_sections); 1110f75da0c8SAlexey Lapshin if (Config.DiscardMode == DiscardType::All) { 1111f75da0c8SAlexey Lapshin Config.StripDebug = true; 1112f75da0c8SAlexey Lapshin ELFConfig.KeepFileSymbols = true; 1113f75da0c8SAlexey Lapshin } 111486e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol)) 1115f75da0c8SAlexey Lapshin if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create( 1116f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1117f75da0c8SAlexey Lapshin return std::move(E); 111886e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols)) 1119f75da0c8SAlexey Lapshin if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc, 1120f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, 1121f75da0c8SAlexey Lapshin ErrorCallback)) 1122f75da0c8SAlexey Lapshin return std::move(E); 112386e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol)) 1124f75da0c8SAlexey Lapshin if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create( 1125f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1126f75da0c8SAlexey Lapshin return std::move(E); 112786e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols)) 1128f75da0c8SAlexey Lapshin if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc, 1129f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, 1130f75da0c8SAlexey Lapshin ErrorCallback)) 1131f75da0c8SAlexey Lapshin return std::move(E); 113286e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol)) 1133f75da0c8SAlexey Lapshin if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create( 1134f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1135f75da0c8SAlexey Lapshin return std::move(E); 113686e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols)) 1137f75da0c8SAlexey Lapshin if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc, 1138f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, 1139f75da0c8SAlexey Lapshin ErrorCallback)) 1140f75da0c8SAlexey Lapshin return std::move(E); 114186e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol)) 1142f75da0c8SAlexey Lapshin if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create( 1143f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1144f75da0c8SAlexey Lapshin return std::move(E); 114586e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols)) 1146f75da0c8SAlexey Lapshin if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc, 1147f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, 1148f75da0c8SAlexey Lapshin ErrorCallback)) 1149f75da0c8SAlexey Lapshin return std::move(E); 115086e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol)) 1151f75da0c8SAlexey Lapshin if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( 1152f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1153f75da0c8SAlexey Lapshin return std::move(E); 115486e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols)) 1155f75da0c8SAlexey Lapshin if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc, 1156f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, 1157f75da0c8SAlexey Lapshin ErrorCallback)) 1158f75da0c8SAlexey Lapshin return std::move(E); 115986e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol)) 1160f75da0c8SAlexey Lapshin if (Error E = 1161f75da0c8SAlexey Lapshin Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create( 1162f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1163f75da0c8SAlexey Lapshin return std::move(E); 116486e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols)) 1165f75da0c8SAlexey Lapshin if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc, 1166f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, 1167f75da0c8SAlexey Lapshin ErrorCallback)) 1168f75da0c8SAlexey Lapshin return std::move(E); 116986e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol)) 1170f75da0c8SAlexey Lapshin if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create( 1171f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1172f75da0c8SAlexey Lapshin return std::move(E); 117386e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols)) 1174f75da0c8SAlexey Lapshin if (Error E = 1175f75da0c8SAlexey Lapshin addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(), 1176f75da0c8SAlexey Lapshin SymbolMatchStyle, ErrorCallback)) 1177f75da0c8SAlexey Lapshin return std::move(E); 11784946cc37SIlia Kuklin for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol)) 11794946cc37SIlia Kuklin if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create( 11804946cc37SIlia Kuklin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 11814946cc37SIlia Kuklin return std::move(E); 11824946cc37SIlia Kuklin for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols)) 11834946cc37SIlia Kuklin if (Error E = 11844946cc37SIlia Kuklin addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(), 11854946cc37SIlia Kuklin SymbolMatchStyle, ErrorCallback)) 11864946cc37SIlia Kuklin return std::move(E); 1187f75da0c8SAlexey Lapshin for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) { 1188f75da0c8SAlexey Lapshin Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue()); 1189f75da0c8SAlexey Lapshin if (!SymInfo) 1190f75da0c8SAlexey Lapshin return SymInfo.takeError(); 1191f75da0c8SAlexey Lapshin 1192f75da0c8SAlexey Lapshin Config.SymbolsToAdd.push_back(*SymInfo); 1193f75da0c8SAlexey Lapshin } 119407d8a457SIlia Kuklin for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbol_visibility)) { 119507d8a457SIlia Kuklin if (!StringRef(Arg->getValue()).contains('=')) 119607d8a457SIlia Kuklin return createStringError(errc::invalid_argument, 119707d8a457SIlia Kuklin "bad format for --set-symbol-visibility"); 119807d8a457SIlia Kuklin auto [Sym, Visibility] = StringRef(Arg->getValue()).split('='); 119907d8a457SIlia Kuklin Expected<uint8_t> Type = parseVisibilityType(Visibility); 120007d8a457SIlia Kuklin if (!Type) 120107d8a457SIlia Kuklin return Type.takeError(); 120207d8a457SIlia Kuklin ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type); 120307d8a457SIlia Kuklin if (Error E = ELFConfig.SymbolsToSetVisibility.back().first.addMatcher( 120407d8a457SIlia Kuklin NameOrPattern::create(Sym, SymbolMatchStyle, ErrorCallback))) 120507d8a457SIlia Kuklin return std::move(E); 120607d8a457SIlia Kuklin } 120707d8a457SIlia Kuklin for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbols_visibility)) { 120807d8a457SIlia Kuklin if (!StringRef(Arg->getValue()).contains('=')) 120907d8a457SIlia Kuklin return createStringError(errc::invalid_argument, 121007d8a457SIlia Kuklin "bad format for --set-symbols-visibility"); 121107d8a457SIlia Kuklin auto [File, Visibility] = StringRef(Arg->getValue()).split('='); 121207d8a457SIlia Kuklin Expected<uint8_t> Type = parseVisibilityType(Visibility); 121307d8a457SIlia Kuklin if (!Type) 121407d8a457SIlia Kuklin return Type.takeError(); 121507d8a457SIlia Kuklin ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type); 121607d8a457SIlia Kuklin if (Error E = 121707d8a457SIlia Kuklin addSymbolsFromFile(ELFConfig.SymbolsToSetVisibility.back().first, 121807d8a457SIlia Kuklin DC.Alloc, File, SymbolMatchStyle, ErrorCallback)) 121907d8a457SIlia Kuklin return std::move(E); 122007d8a457SIlia Kuklin } 1221f75da0c8SAlexey Lapshin 1222f75da0c8SAlexey Lapshin ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links); 1223f75da0c8SAlexey Lapshin 1224f75da0c8SAlexey Lapshin Config.DeterministicArchives = InputArgs.hasFlag( 1225f75da0c8SAlexey Lapshin OBJCOPY_enable_deterministic_archives, 1226f75da0c8SAlexey Lapshin OBJCOPY_disable_deterministic_archives, /*default=*/true); 1227f75da0c8SAlexey Lapshin 1228f75da0c8SAlexey Lapshin Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates); 1229f75da0c8SAlexey Lapshin 1230f75da0c8SAlexey Lapshin if (Config.PreserveDates && 1231f75da0c8SAlexey Lapshin (Config.OutputFilename == "-" || Config.InputFilename == "-")) 1232f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1233f75da0c8SAlexey Lapshin "--preserve-dates requires a file"); 1234f75da0c8SAlexey Lapshin 123586e8164aSKazu Hirata for (auto *Arg : InputArgs) 1236f75da0c8SAlexey Lapshin if (Arg->getOption().matches(OBJCOPY_set_start)) { 1237f75da0c8SAlexey Lapshin auto EAddr = getAsInteger<uint64_t>(Arg->getValue()); 1238f75da0c8SAlexey Lapshin if (!EAddr) 1239f75da0c8SAlexey Lapshin return createStringError( 1240f75da0c8SAlexey Lapshin EAddr.getError(), "bad entry point address: '%s'", Arg->getValue()); 1241f75da0c8SAlexey Lapshin 1242f75da0c8SAlexey Lapshin ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; }; 1243f75da0c8SAlexey Lapshin } else if (Arg->getOption().matches(OBJCOPY_change_start)) { 1244f75da0c8SAlexey Lapshin auto EIncr = getAsInteger<int64_t>(Arg->getValue()); 1245f75da0c8SAlexey Lapshin if (!EIncr) 1246f75da0c8SAlexey Lapshin return createStringError(EIncr.getError(), 1247f75da0c8SAlexey Lapshin "bad entry point increment: '%s'", 1248f75da0c8SAlexey Lapshin Arg->getValue()); 1249f75da0c8SAlexey Lapshin auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr) 1250f75da0c8SAlexey Lapshin : [](uint64_t A) { return A; }; 1251f75da0c8SAlexey Lapshin ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) { 1252f75da0c8SAlexey Lapshin return Expr(EAddr) + *EIncr; 1253f75da0c8SAlexey Lapshin }; 1254f75da0c8SAlexey Lapshin } 1255f75da0c8SAlexey Lapshin 1256*10772807SIgor Kudrin for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_note)) { 1257*10772807SIgor Kudrin Expected<RemoveNoteInfo> NoteInfo = parseRemoveNoteInfo(Arg->getValue()); 1258*10772807SIgor Kudrin if (!NoteInfo) 1259*10772807SIgor Kudrin return NoteInfo.takeError(); 1260*10772807SIgor Kudrin 1261*10772807SIgor Kudrin ELFConfig.NotesToRemove.push_back(*NoteInfo); 1262*10772807SIgor Kudrin } 1263*10772807SIgor Kudrin 1264*10772807SIgor Kudrin if (!ELFConfig.NotesToRemove.empty()) { 1265*10772807SIgor Kudrin if (!Config.ToRemove.empty()) 1266*10772807SIgor Kudrin return createStringError( 1267*10772807SIgor Kudrin errc::invalid_argument, 1268*10772807SIgor Kudrin "cannot specify both --remove-note and --remove-section"); 1269*10772807SIgor Kudrin if (!Config.AddSection.empty()) 1270*10772807SIgor Kudrin return createStringError( 1271*10772807SIgor Kudrin errc::invalid_argument, 1272*10772807SIgor Kudrin "cannot specify both --remove-note and --add-section"); 1273*10772807SIgor Kudrin if (!Config.UpdateSection.empty()) 1274*10772807SIgor Kudrin return createStringError( 1275*10772807SIgor Kudrin errc::invalid_argument, 1276*10772807SIgor Kudrin "cannot specify both --remove-note and --update-section"); 1277*10772807SIgor Kudrin } 1278*10772807SIgor Kudrin 1279f75da0c8SAlexey Lapshin if (Config.DecompressDebugSections && 1280f75da0c8SAlexey Lapshin Config.CompressionType != DebugCompressionType::None) { 1281f75da0c8SAlexey Lapshin return createStringError( 1282f75da0c8SAlexey Lapshin errc::invalid_argument, 1283f75da0c8SAlexey Lapshin "cannot specify both --compress-debug-sections and " 1284f75da0c8SAlexey Lapshin "--decompress-debug-sections"); 1285f75da0c8SAlexey Lapshin } 1286f75da0c8SAlexey Lapshin 1287f75da0c8SAlexey Lapshin if (Config.ExtractPartition && Config.ExtractMainPartition) 1288f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1289f75da0c8SAlexey Lapshin "cannot specify --extract-partition together with " 1290f75da0c8SAlexey Lapshin "--extract-main-partition"); 1291f75da0c8SAlexey Lapshin 1292f75da0c8SAlexey Lapshin DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1293f75da0c8SAlexey Lapshin return std::move(DC); 1294f75da0c8SAlexey Lapshin } 1295f75da0c8SAlexey Lapshin 1296a91c77eeSNico Weber // parseInstallNameToolOptions returns the config and sets the input arguments. 1297a91c77eeSNico Weber // If a help flag is set then parseInstallNameToolOptions will print the help 1298f75da0c8SAlexey Lapshin // messege and exit. 1299f75da0c8SAlexey Lapshin Expected<DriverConfig> 1300f75da0c8SAlexey Lapshin objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) { 1301f75da0c8SAlexey Lapshin DriverConfig DC; 1302f75da0c8SAlexey Lapshin ConfigManager ConfigMgr; 1303f75da0c8SAlexey Lapshin CommonConfig &Config = ConfigMgr.Common; 1304f75da0c8SAlexey Lapshin MachOConfig &MachOConfig = ConfigMgr.MachO; 1305f75da0c8SAlexey Lapshin InstallNameToolOptTable T; 1306f75da0c8SAlexey Lapshin unsigned MissingArgumentIndex, MissingArgumentCount; 1307f75da0c8SAlexey Lapshin llvm::opt::InputArgList InputArgs = 1308f75da0c8SAlexey Lapshin T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1309f75da0c8SAlexey Lapshin 1310f75da0c8SAlexey Lapshin if (MissingArgumentCount) 1311f75da0c8SAlexey Lapshin return createStringError( 1312f75da0c8SAlexey Lapshin errc::invalid_argument, 1313f75da0c8SAlexey Lapshin "missing argument to " + 1314f75da0c8SAlexey Lapshin StringRef(InputArgs.getArgString(MissingArgumentIndex)) + 1315f75da0c8SAlexey Lapshin " option"); 1316f75da0c8SAlexey Lapshin 1317f75da0c8SAlexey Lapshin if (InputArgs.size() == 0) { 1318f75da0c8SAlexey Lapshin printHelp(T, errs(), ToolType::InstallNameTool); 1319f75da0c8SAlexey Lapshin exit(1); 1320f75da0c8SAlexey Lapshin } 1321f75da0c8SAlexey Lapshin 1322f75da0c8SAlexey Lapshin if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) { 1323f75da0c8SAlexey Lapshin printHelp(T, outs(), ToolType::InstallNameTool); 1324f75da0c8SAlexey Lapshin exit(0); 1325f75da0c8SAlexey Lapshin } 1326f75da0c8SAlexey Lapshin 1327f75da0c8SAlexey Lapshin if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) { 1328f75da0c8SAlexey Lapshin outs() << "llvm-install-name-tool, compatible with cctools " 1329f75da0c8SAlexey Lapshin "install_name_tool\n"; 1330f75da0c8SAlexey Lapshin cl::PrintVersionMessage(); 1331f75da0c8SAlexey Lapshin exit(0); 1332f75da0c8SAlexey Lapshin } 1333f75da0c8SAlexey Lapshin 133486e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath)) 1335f75da0c8SAlexey Lapshin MachOConfig.RPathToAdd.push_back(Arg->getValue()); 1336f75da0c8SAlexey Lapshin 1337f75da0c8SAlexey Lapshin for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath)) 1338f75da0c8SAlexey Lapshin MachOConfig.RPathToPrepend.push_back(Arg->getValue()); 1339f75da0c8SAlexey Lapshin 134086e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) { 1341f75da0c8SAlexey Lapshin StringRef RPath = Arg->getValue(); 1342f75da0c8SAlexey Lapshin 1343f75da0c8SAlexey Lapshin // Cannot add and delete the same rpath at the same time. 1344f75da0c8SAlexey Lapshin if (is_contained(MachOConfig.RPathToAdd, RPath)) 1345f75da0c8SAlexey Lapshin return createStringError( 1346f75da0c8SAlexey Lapshin errc::invalid_argument, 1347f75da0c8SAlexey Lapshin "cannot specify both -add_rpath '%s' and -delete_rpath '%s'", 1348f75da0c8SAlexey Lapshin RPath.str().c_str(), RPath.str().c_str()); 1349f75da0c8SAlexey Lapshin if (is_contained(MachOConfig.RPathToPrepend, RPath)) 1350f75da0c8SAlexey Lapshin return createStringError( 1351f75da0c8SAlexey Lapshin errc::invalid_argument, 1352f75da0c8SAlexey Lapshin "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'", 1353f75da0c8SAlexey Lapshin RPath.str().c_str(), RPath.str().c_str()); 1354f75da0c8SAlexey Lapshin 1355f75da0c8SAlexey Lapshin MachOConfig.RPathsToRemove.insert(RPath); 1356f75da0c8SAlexey Lapshin } 1357f75da0c8SAlexey Lapshin 1358f75da0c8SAlexey Lapshin for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) { 1359f75da0c8SAlexey Lapshin StringRef Old = Arg->getValue(0); 1360f75da0c8SAlexey Lapshin StringRef New = Arg->getValue(1); 1361f75da0c8SAlexey Lapshin 1362f75da0c8SAlexey Lapshin auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; }; 1363f75da0c8SAlexey Lapshin 1364f75da0c8SAlexey Lapshin // Cannot specify duplicate -rpath entries 1365f75da0c8SAlexey Lapshin auto It1 = find_if( 1366f75da0c8SAlexey Lapshin MachOConfig.RPathsToUpdate, 1367f75da0c8SAlexey Lapshin [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) { 1368f75da0c8SAlexey Lapshin return Match(OldNew.getFirst()) || Match(OldNew.getSecond()); 1369f75da0c8SAlexey Lapshin }); 1370f75da0c8SAlexey Lapshin if (It1 != MachOConfig.RPathsToUpdate.end()) 1371f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1372f75da0c8SAlexey Lapshin "cannot specify both -rpath '" + 1373f75da0c8SAlexey Lapshin It1->getFirst() + "' '" + It1->getSecond() + 1374f75da0c8SAlexey Lapshin "' and -rpath '" + Old + "' '" + New + "'"); 1375f75da0c8SAlexey Lapshin 1376f75da0c8SAlexey Lapshin // Cannot specify the same rpath under both -delete_rpath and -rpath 1377f75da0c8SAlexey Lapshin auto It2 = find_if(MachOConfig.RPathsToRemove, Match); 1378f75da0c8SAlexey Lapshin if (It2 != MachOConfig.RPathsToRemove.end()) 1379f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1380f75da0c8SAlexey Lapshin "cannot specify both -delete_rpath '" + *It2 + 1381f75da0c8SAlexey Lapshin "' and -rpath '" + Old + "' '" + New + "'"); 1382f75da0c8SAlexey Lapshin 1383f75da0c8SAlexey Lapshin // Cannot specify the same rpath under both -add_rpath and -rpath 1384f75da0c8SAlexey Lapshin auto It3 = find_if(MachOConfig.RPathToAdd, Match); 1385f75da0c8SAlexey Lapshin if (It3 != MachOConfig.RPathToAdd.end()) 1386f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1387f75da0c8SAlexey Lapshin "cannot specify both -add_rpath '" + *It3 + 1388f75da0c8SAlexey Lapshin "' and -rpath '" + Old + "' '" + New + "'"); 1389f75da0c8SAlexey Lapshin 1390f75da0c8SAlexey Lapshin // Cannot specify the same rpath under both -prepend_rpath and -rpath. 1391f75da0c8SAlexey Lapshin auto It4 = find_if(MachOConfig.RPathToPrepend, Match); 1392f75da0c8SAlexey Lapshin if (It4 != MachOConfig.RPathToPrepend.end()) 1393f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1394f75da0c8SAlexey Lapshin "cannot specify both -prepend_rpath '" + *It4 + 1395f75da0c8SAlexey Lapshin "' and -rpath '" + Old + "' '" + New + "'"); 1396f75da0c8SAlexey Lapshin 1397f75da0c8SAlexey Lapshin MachOConfig.RPathsToUpdate.insert({Old, New}); 1398f75da0c8SAlexey Lapshin } 1399f75da0c8SAlexey Lapshin 1400f75da0c8SAlexey Lapshin if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) { 1401f75da0c8SAlexey Lapshin MachOConfig.SharedLibId = Arg->getValue(); 1402f75da0c8SAlexey Lapshin if (MachOConfig.SharedLibId->empty()) 1403f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1404f75da0c8SAlexey Lapshin "cannot specify an empty id"); 1405f75da0c8SAlexey Lapshin } 1406f75da0c8SAlexey Lapshin 1407f75da0c8SAlexey Lapshin for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change)) 1408f75da0c8SAlexey Lapshin MachOConfig.InstallNamesToUpdate.insert( 1409f75da0c8SAlexey Lapshin {Arg->getValue(0), Arg->getValue(1)}); 1410f75da0c8SAlexey Lapshin 1411f75da0c8SAlexey Lapshin MachOConfig.RemoveAllRpaths = 1412f75da0c8SAlexey Lapshin InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths); 1413f75da0c8SAlexey Lapshin 1414f75da0c8SAlexey Lapshin SmallVector<StringRef, 2> Positional; 141586e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN)) 1416f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, "unknown argument '%s'", 1417f75da0c8SAlexey Lapshin Arg->getAsString(InputArgs).c_str()); 141886e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT)) 1419f75da0c8SAlexey Lapshin Positional.push_back(Arg->getValue()); 1420f75da0c8SAlexey Lapshin if (Positional.empty()) 1421f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, "no input file specified"); 1422f75da0c8SAlexey Lapshin if (Positional.size() > 1) 1423f75da0c8SAlexey Lapshin return createStringError( 1424f75da0c8SAlexey Lapshin errc::invalid_argument, 1425f75da0c8SAlexey Lapshin "llvm-install-name-tool expects a single input file"); 1426f75da0c8SAlexey Lapshin Config.InputFilename = Positional[0]; 1427f75da0c8SAlexey Lapshin Config.OutputFilename = Positional[0]; 1428f75da0c8SAlexey Lapshin 1429fa535452SKeith Smiley Expected<OwningBinary<Binary>> BinaryOrErr = 1430fa535452SKeith Smiley createBinary(Config.InputFilename); 1431fa535452SKeith Smiley if (!BinaryOrErr) 1432fa535452SKeith Smiley return createFileError(Config.InputFilename, BinaryOrErr.takeError()); 1433fa535452SKeith Smiley auto *Binary = (*BinaryOrErr).getBinary(); 1434fa535452SKeith Smiley if (!Binary->isMachO() && !Binary->isMachOUniversalBinary()) 1435fa535452SKeith Smiley return createStringError(errc::invalid_argument, 1436fa535452SKeith Smiley "input file: %s is not a Mach-O file", 1437fa535452SKeith Smiley Config.InputFilename.str().c_str()); 1438fa535452SKeith Smiley 1439f75da0c8SAlexey Lapshin DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1440f75da0c8SAlexey Lapshin return std::move(DC); 1441f75da0c8SAlexey Lapshin } 1442f75da0c8SAlexey Lapshin 1443f75da0c8SAlexey Lapshin Expected<DriverConfig> 144494fba14fSRichard Howell objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr, 144594fba14fSRichard Howell function_ref<Error(Error)> ErrorCallback) { 1446f75da0c8SAlexey Lapshin DriverConfig DC; 1447f75da0c8SAlexey Lapshin ConfigManager ConfigMgr; 1448f75da0c8SAlexey Lapshin CommonConfig &Config = ConfigMgr.Common; 144959172194SRichard Howell MachOConfig &MachOConfig = ConfigMgr.MachO; 1450f75da0c8SAlexey Lapshin BitcodeStripOptTable T; 1451f75da0c8SAlexey Lapshin unsigned MissingArgumentIndex, MissingArgumentCount; 1452f75da0c8SAlexey Lapshin opt::InputArgList InputArgs = 1453f75da0c8SAlexey Lapshin T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1454f75da0c8SAlexey Lapshin 1455f75da0c8SAlexey Lapshin if (InputArgs.size() == 0) { 1456f75da0c8SAlexey Lapshin printHelp(T, errs(), ToolType::BitcodeStrip); 1457f75da0c8SAlexey Lapshin exit(1); 1458f75da0c8SAlexey Lapshin } 1459f75da0c8SAlexey Lapshin 1460f75da0c8SAlexey Lapshin if (InputArgs.hasArg(BITCODE_STRIP_help)) { 1461f75da0c8SAlexey Lapshin printHelp(T, outs(), ToolType::BitcodeStrip); 1462f75da0c8SAlexey Lapshin exit(0); 1463f75da0c8SAlexey Lapshin } 1464f75da0c8SAlexey Lapshin 1465f75da0c8SAlexey Lapshin if (InputArgs.hasArg(BITCODE_STRIP_version)) { 1466f75da0c8SAlexey Lapshin outs() << "llvm-bitcode-strip, compatible with cctools " 1467f75da0c8SAlexey Lapshin "bitcode_strip\n"; 1468f75da0c8SAlexey Lapshin cl::PrintVersionMessage(); 1469f75da0c8SAlexey Lapshin exit(0); 1470f75da0c8SAlexey Lapshin } 1471f75da0c8SAlexey Lapshin 1472f75da0c8SAlexey Lapshin for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN)) 1473f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, "unknown argument '%s'", 1474f75da0c8SAlexey Lapshin Arg->getAsString(InputArgs).c_str()); 1475f75da0c8SAlexey Lapshin 1476f75da0c8SAlexey Lapshin SmallVector<StringRef, 2> Positional; 1477f75da0c8SAlexey Lapshin for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT)) 1478f75da0c8SAlexey Lapshin Positional.push_back(Arg->getValue()); 1479f75da0c8SAlexey Lapshin if (Positional.size() > 1) 1480f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1481f75da0c8SAlexey Lapshin "llvm-bitcode-strip expects a single input file"); 1482f75da0c8SAlexey Lapshin assert(!Positional.empty()); 1483f75da0c8SAlexey Lapshin Config.InputFilename = Positional[0]; 14848e6d2fe4SRichard Howell 14858e6d2fe4SRichard Howell if (!InputArgs.hasArg(BITCODE_STRIP_output)) { 14868e6d2fe4SRichard Howell return createStringError(errc::invalid_argument, 14878e6d2fe4SRichard Howell "-o is a required argument"); 14888e6d2fe4SRichard Howell } 14898e6d2fe4SRichard Howell Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output); 1490f75da0c8SAlexey Lapshin 149194fba14fSRichard Howell if (!InputArgs.hasArg(BITCODE_STRIP_remove)) 149294fba14fSRichard Howell return createStringError(errc::invalid_argument, "no action specified"); 149394fba14fSRichard Howell 149459172194SRichard Howell // We only support -r for now, which removes all bitcode sections and 149559172194SRichard Howell // the __LLVM segment if it's now empty. 149694fba14fSRichard Howell cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1497d991aa91SKeith Smiley "__LLVM,__asm", MatchStyle::Literal, ErrorCallback))); 1498d991aa91SKeith Smiley cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1499d991aa91SKeith Smiley "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback))); 1500d991aa91SKeith Smiley cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 150194fba14fSRichard Howell "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback))); 1502d991aa91SKeith Smiley cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1503d991aa91SKeith Smiley "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback))); 1504d991aa91SKeith Smiley cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1505d991aa91SKeith Smiley "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback))); 150659172194SRichard Howell MachOConfig.EmptySegmentsToRemove.insert("__LLVM"); 150794fba14fSRichard Howell 1508f75da0c8SAlexey Lapshin DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1509f75da0c8SAlexey Lapshin return std::move(DC); 1510f75da0c8SAlexey Lapshin } 1511f75da0c8SAlexey Lapshin 1512a91c77eeSNico Weber // parseStripOptions returns the config and sets the input arguments. If a 1513a91c77eeSNico Weber // help flag is set then parseStripOptions will print the help messege and 1514f75da0c8SAlexey Lapshin // exit. 1515f75da0c8SAlexey Lapshin Expected<DriverConfig> 1516f75da0c8SAlexey Lapshin objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr, 1517f75da0c8SAlexey Lapshin function_ref<Error(Error)> ErrorCallback) { 1518f75da0c8SAlexey Lapshin const char *const *DashDash = 1519ce9f007cSKazu Hirata llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; }); 152038818b60Sserge-sans-paille ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash); 1521f75da0c8SAlexey Lapshin if (DashDash != RawArgsArr.end()) 1522f75da0c8SAlexey Lapshin DashDash = std::next(DashDash); 1523f75da0c8SAlexey Lapshin 1524f75da0c8SAlexey Lapshin StripOptTable T; 1525f75da0c8SAlexey Lapshin unsigned MissingArgumentIndex, MissingArgumentCount; 1526f75da0c8SAlexey Lapshin llvm::opt::InputArgList InputArgs = 1527f75da0c8SAlexey Lapshin T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1528f75da0c8SAlexey Lapshin 1529f75da0c8SAlexey Lapshin if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) { 1530f75da0c8SAlexey Lapshin printHelp(T, errs(), ToolType::Strip); 1531f75da0c8SAlexey Lapshin exit(1); 1532f75da0c8SAlexey Lapshin } 1533f75da0c8SAlexey Lapshin 1534f75da0c8SAlexey Lapshin if (InputArgs.hasArg(STRIP_help)) { 1535f75da0c8SAlexey Lapshin printHelp(T, outs(), ToolType::Strip); 1536f75da0c8SAlexey Lapshin exit(0); 1537f75da0c8SAlexey Lapshin } 1538f75da0c8SAlexey Lapshin 1539f75da0c8SAlexey Lapshin if (InputArgs.hasArg(STRIP_version)) { 1540f75da0c8SAlexey Lapshin outs() << "llvm-strip, compatible with GNU strip\n"; 1541f75da0c8SAlexey Lapshin cl::PrintVersionMessage(); 1542f75da0c8SAlexey Lapshin exit(0); 1543f75da0c8SAlexey Lapshin } 1544f75da0c8SAlexey Lapshin 1545f75da0c8SAlexey Lapshin SmallVector<StringRef, 2> Positional; 154686e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN)) 1547f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, "unknown argument '%s'", 1548f75da0c8SAlexey Lapshin Arg->getAsString(InputArgs).c_str()); 154986e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(STRIP_INPUT)) 1550f75da0c8SAlexey Lapshin Positional.push_back(Arg->getValue()); 1551f75da0c8SAlexey Lapshin std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional)); 1552f75da0c8SAlexey Lapshin 1553f75da0c8SAlexey Lapshin if (Positional.empty()) 1554f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, "no input file specified"); 1555f75da0c8SAlexey Lapshin 1556f75da0c8SAlexey Lapshin if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output)) 1557f75da0c8SAlexey Lapshin return createStringError( 1558f75da0c8SAlexey Lapshin errc::invalid_argument, 1559f75da0c8SAlexey Lapshin "multiple input files cannot be used in combination with -o"); 1560f75da0c8SAlexey Lapshin 1561f75da0c8SAlexey Lapshin ConfigManager ConfigMgr; 1562f75da0c8SAlexey Lapshin CommonConfig &Config = ConfigMgr.Common; 1563f75da0c8SAlexey Lapshin ELFConfig &ELFConfig = ConfigMgr.ELF; 1564f75da0c8SAlexey Lapshin MachOConfig &MachOConfig = ConfigMgr.MachO; 1565f75da0c8SAlexey Lapshin 1566f75da0c8SAlexey Lapshin if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard)) 1567f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1568f75da0c8SAlexey Lapshin "--regex and --wildcard are incompatible"); 1569f75da0c8SAlexey Lapshin MatchStyle SectionMatchStyle = 1570f75da0c8SAlexey Lapshin InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard; 1571f75da0c8SAlexey Lapshin MatchStyle SymbolMatchStyle 1572f75da0c8SAlexey Lapshin = InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex 1573f75da0c8SAlexey Lapshin : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard 1574f75da0c8SAlexey Lapshin : MatchStyle::Literal; 1575f75da0c8SAlexey Lapshin ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links); 1576f75da0c8SAlexey Lapshin Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug); 1577f75da0c8SAlexey Lapshin 1578c37accf0SFangrui Song if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals)) 1579c37accf0SFangrui Song Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all) 1580f75da0c8SAlexey Lapshin ? DiscardType::All 1581f75da0c8SAlexey Lapshin : DiscardType::Locals; 1582f75da0c8SAlexey Lapshin Config.StripSections = InputArgs.hasArg(STRIP_strip_sections); 1583f75da0c8SAlexey Lapshin Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded); 1584f75da0c8SAlexey Lapshin if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all)) 1585f75da0c8SAlexey Lapshin Config.StripAll = Arg->getOption().getID() == STRIP_strip_all; 1586f75da0c8SAlexey Lapshin Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu); 1587f75da0c8SAlexey Lapshin MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols); 1588f75da0c8SAlexey Lapshin Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug); 1589f75da0c8SAlexey Lapshin ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols); 1590f75da0c8SAlexey Lapshin MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined); 1591f75da0c8SAlexey Lapshin 159286e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(STRIP_keep_section)) 1593f75da0c8SAlexey Lapshin if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( 1594f75da0c8SAlexey Lapshin Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1595f75da0c8SAlexey Lapshin return std::move(E); 1596f75da0c8SAlexey Lapshin 159786e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(STRIP_remove_section)) 1598f75da0c8SAlexey Lapshin if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( 1599f75da0c8SAlexey Lapshin Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1600f75da0c8SAlexey Lapshin return std::move(E); 1601f75da0c8SAlexey Lapshin 160286e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol)) 1603f75da0c8SAlexey Lapshin if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( 1604f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1605f75da0c8SAlexey Lapshin return std::move(E); 1606f75da0c8SAlexey Lapshin 160786e8164aSKazu Hirata for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol)) 1608f75da0c8SAlexey Lapshin if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create( 1609f75da0c8SAlexey Lapshin Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1610f75da0c8SAlexey Lapshin return std::move(E); 1611f75da0c8SAlexey Lapshin 1612f75da0c8SAlexey Lapshin if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug && 16133787de40SJohn McIver !Config.OnlyKeepDebug && !Config.StripUnneeded && 16143787de40SJohn McIver Config.DiscardMode == DiscardType::None && !Config.StripAllGNU && 16153787de40SJohn McIver Config.SymbolsToRemove.empty()) 1616f75da0c8SAlexey Lapshin Config.StripAll = true; 1617f75da0c8SAlexey Lapshin 1618f75da0c8SAlexey Lapshin if (Config.DiscardMode == DiscardType::All) { 1619f75da0c8SAlexey Lapshin Config.StripDebug = true; 1620f75da0c8SAlexey Lapshin ELFConfig.KeepFileSymbols = true; 1621f75da0c8SAlexey Lapshin } 1622f75da0c8SAlexey Lapshin 1623f75da0c8SAlexey Lapshin Config.DeterministicArchives = 1624f75da0c8SAlexey Lapshin InputArgs.hasFlag(STRIP_enable_deterministic_archives, 1625f75da0c8SAlexey Lapshin STRIP_disable_deterministic_archives, /*default=*/true); 1626f75da0c8SAlexey Lapshin 1627f75da0c8SAlexey Lapshin Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates); 1628f75da0c8SAlexey Lapshin Config.InputFormat = FileFormat::Unspecified; 1629f75da0c8SAlexey Lapshin Config.OutputFormat = FileFormat::Unspecified; 1630f75da0c8SAlexey Lapshin 1631f75da0c8SAlexey Lapshin DriverConfig DC; 1632f75da0c8SAlexey Lapshin if (Positional.size() == 1) { 1633f75da0c8SAlexey Lapshin Config.InputFilename = Positional[0]; 1634f75da0c8SAlexey Lapshin Config.OutputFilename = 1635f75da0c8SAlexey Lapshin InputArgs.getLastArgValue(STRIP_output, Positional[0]); 1636f75da0c8SAlexey Lapshin DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1637f75da0c8SAlexey Lapshin } else { 1638f75da0c8SAlexey Lapshin StringMap<unsigned> InputFiles; 1639f75da0c8SAlexey Lapshin for (StringRef Filename : Positional) { 1640f75da0c8SAlexey Lapshin if (InputFiles[Filename]++ == 1) { 1641f75da0c8SAlexey Lapshin if (Filename == "-") 1642f75da0c8SAlexey Lapshin return createStringError( 1643f75da0c8SAlexey Lapshin errc::invalid_argument, 1644f75da0c8SAlexey Lapshin "cannot specify '-' as an input file more than once"); 1645f75da0c8SAlexey Lapshin if (Error E = ErrorCallback(createStringError( 1646f75da0c8SAlexey Lapshin errc::invalid_argument, "'%s' was already specified", 1647f75da0c8SAlexey Lapshin Filename.str().c_str()))) 1648f75da0c8SAlexey Lapshin return std::move(E); 1649f75da0c8SAlexey Lapshin } 1650f75da0c8SAlexey Lapshin Config.InputFilename = Filename; 1651f75da0c8SAlexey Lapshin Config.OutputFilename = Filename; 1652f75da0c8SAlexey Lapshin DC.CopyConfigs.push_back(ConfigMgr); 1653f75da0c8SAlexey Lapshin } 1654f75da0c8SAlexey Lapshin } 1655f75da0c8SAlexey Lapshin 1656f75da0c8SAlexey Lapshin if (Config.PreserveDates && (is_contained(Positional, "-") || 1657f75da0c8SAlexey Lapshin InputArgs.getLastArgValue(STRIP_output) == "-")) 1658f75da0c8SAlexey Lapshin return createStringError(errc::invalid_argument, 1659f75da0c8SAlexey Lapshin "--preserve-dates requires a file"); 1660f75da0c8SAlexey Lapshin 1661f75da0c8SAlexey Lapshin return std::move(DC); 1662f75da0c8SAlexey Lapshin } 1663