1 //===- ObjcopyOptions.cpp -------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ObjcopyOptions.h" 10 #include "llvm/ADT/SmallVector.h" 11 #include "llvm/ADT/StringExtras.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/ADT/StringSwitch.h" 14 #include "llvm/BinaryFormat/COFF.h" 15 #include "llvm/ObjCopy/CommonConfig.h" 16 #include "llvm/ObjCopy/ConfigManager.h" 17 #include "llvm/ObjCopy/MachO/MachOConfig.h" 18 #include "llvm/Object/Binary.h" 19 #include "llvm/Option/Arg.h" 20 #include "llvm/Option/ArgList.h" 21 #include "llvm/Support/CRC.h" 22 #include "llvm/Support/CommandLine.h" 23 #include "llvm/Support/Compression.h" 24 #include "llvm/Support/Errc.h" 25 #include "llvm/Support/Error.h" 26 #include "llvm/Support/MemoryBuffer.h" 27 28 using namespace llvm; 29 using namespace llvm::objcopy; 30 using namespace llvm::object; 31 using namespace llvm::opt; 32 33 namespace { 34 enum ObjcopyID { 35 OBJCOPY_INVALID = 0, // This is not an option ID. 36 #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__), 37 #include "ObjcopyOpts.inc" 38 #undef OPTION 39 }; 40 41 namespace objcopy_opt { 42 #define OPTTABLE_STR_TABLE_CODE 43 #include "ObjcopyOpts.inc" 44 #undef OPTTABLE_STR_TABLE_CODE 45 46 #define OPTTABLE_PREFIXES_TABLE_CODE 47 #include "ObjcopyOpts.inc" 48 #undef OPTTABLE_PREFIXES_TABLE_CODE 49 50 static constexpr opt::OptTable::Info ObjcopyInfoTable[] = { 51 #define OPTION(...) \ 52 LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__), 53 #include "ObjcopyOpts.inc" 54 #undef OPTION 55 }; 56 } // namespace objcopy_opt 57 58 class ObjcopyOptTable : public opt::GenericOptTable { 59 public: 60 ObjcopyOptTable() 61 : opt::GenericOptTable(objcopy_opt::OptionStrTable, 62 objcopy_opt::OptionPrefixesTable, 63 objcopy_opt::ObjcopyInfoTable) { 64 setGroupedShortOptions(true); 65 setDashDashParsing(true); 66 } 67 }; 68 69 enum InstallNameToolID { 70 INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID. 71 #define OPTION(...) \ 72 LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__), 73 #include "InstallNameToolOpts.inc" 74 #undef OPTION 75 }; 76 77 namespace install_name_tool { 78 #define OPTTABLE_STR_TABLE_CODE 79 #include "InstallNameToolOpts.inc" 80 #undef OPTTABLE_STR_TABLE_CODE 81 82 #define OPTTABLE_PREFIXES_TABLE_CODE 83 #include "InstallNameToolOpts.inc" 84 #undef OPTTABLE_PREFIXES_TABLE_CODE 85 86 static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = { 87 #define OPTION(...) \ 88 LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__), 89 #include "InstallNameToolOpts.inc" 90 #undef OPTION 91 }; 92 } // namespace install_name_tool 93 94 class InstallNameToolOptTable : public opt::GenericOptTable { 95 public: 96 InstallNameToolOptTable() 97 : GenericOptTable(install_name_tool::OptionStrTable, 98 install_name_tool::OptionPrefixesTable, 99 install_name_tool::InstallNameToolInfoTable) {} 100 }; 101 102 enum BitcodeStripID { 103 BITCODE_STRIP_INVALID = 0, // This is not an option ID. 104 #define OPTION(...) \ 105 LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__), 106 #include "BitcodeStripOpts.inc" 107 #undef OPTION 108 }; 109 110 namespace bitcode_strip { 111 #define OPTTABLE_STR_TABLE_CODE 112 #include "BitcodeStripOpts.inc" 113 #undef OPTTABLE_STR_TABLE_CODE 114 115 #define OPTTABLE_PREFIXES_TABLE_CODE 116 #include "BitcodeStripOpts.inc" 117 #undef OPTTABLE_PREFIXES_TABLE_CODE 118 119 static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = { 120 #define OPTION(...) \ 121 LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__), 122 #include "BitcodeStripOpts.inc" 123 #undef OPTION 124 }; 125 } // namespace bitcode_strip 126 127 class BitcodeStripOptTable : public opt::GenericOptTable { 128 public: 129 BitcodeStripOptTable() 130 : opt::GenericOptTable(bitcode_strip::OptionStrTable, 131 bitcode_strip::OptionPrefixesTable, 132 bitcode_strip::BitcodeStripInfoTable) {} 133 }; 134 135 enum StripID { 136 STRIP_INVALID = 0, // This is not an option ID. 137 #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__), 138 #include "StripOpts.inc" 139 #undef OPTION 140 }; 141 142 namespace strip { 143 #define OPTTABLE_STR_TABLE_CODE 144 #include "StripOpts.inc" 145 #undef OPTTABLE_STR_TABLE_CODE 146 147 #define OPTTABLE_PREFIXES_TABLE_CODE 148 #include "StripOpts.inc" 149 #undef OPTTABLE_PREFIXES_TABLE_CODE 150 151 static constexpr opt::OptTable::Info StripInfoTable[] = { 152 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__), 153 #include "StripOpts.inc" 154 #undef OPTION 155 }; 156 } // namespace strip 157 158 class StripOptTable : public opt::GenericOptTable { 159 public: 160 StripOptTable() 161 : GenericOptTable(strip::OptionStrTable, strip::OptionPrefixesTable, 162 strip::StripInfoTable) { 163 setGroupedShortOptions(true); 164 } 165 }; 166 167 } // namespace 168 169 static SectionFlag parseSectionRenameFlag(StringRef SectionName) { 170 return llvm::StringSwitch<SectionFlag>(SectionName) 171 .CaseLower("alloc", SectionFlag::SecAlloc) 172 .CaseLower("load", SectionFlag::SecLoad) 173 .CaseLower("noload", SectionFlag::SecNoload) 174 .CaseLower("readonly", SectionFlag::SecReadonly) 175 .CaseLower("debug", SectionFlag::SecDebug) 176 .CaseLower("code", SectionFlag::SecCode) 177 .CaseLower("data", SectionFlag::SecData) 178 .CaseLower("rom", SectionFlag::SecRom) 179 .CaseLower("merge", SectionFlag::SecMerge) 180 .CaseLower("strings", SectionFlag::SecStrings) 181 .CaseLower("contents", SectionFlag::SecContents) 182 .CaseLower("share", SectionFlag::SecShare) 183 .CaseLower("exclude", SectionFlag::SecExclude) 184 .CaseLower("large", SectionFlag::SecLarge) 185 .Default(SectionFlag::SecNone); 186 } 187 188 static Expected<SectionFlag> 189 parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) { 190 SectionFlag ParsedFlags = SectionFlag::SecNone; 191 for (StringRef Flag : SectionFlags) { 192 SectionFlag ParsedFlag = parseSectionRenameFlag(Flag); 193 if (ParsedFlag == SectionFlag::SecNone) 194 return createStringError( 195 errc::invalid_argument, 196 "unrecognized section flag '%s'. Flags supported for GNU " 197 "compatibility: alloc, load, noload, readonly, exclude, debug, " 198 "code, data, rom, share, contents, merge, strings, large", 199 Flag.str().c_str()); 200 ParsedFlags |= ParsedFlag; 201 } 202 203 return ParsedFlags; 204 } 205 206 static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) { 207 if (!FlagValue.contains('=')) 208 return createStringError(errc::invalid_argument, 209 "bad format for --rename-section: missing '='"); 210 211 // Initial split: ".foo" = ".bar,f1,f2,..." 212 auto Old2New = FlagValue.split('='); 213 SectionRename SR; 214 SR.OriginalName = Old2New.first; 215 216 // Flags split: ".bar" "f1" "f2" ... 217 SmallVector<StringRef, 6> NameAndFlags; 218 Old2New.second.split(NameAndFlags, ','); 219 SR.NewName = NameAndFlags[0]; 220 221 if (NameAndFlags.size() > 1) { 222 Expected<SectionFlag> ParsedFlagSet = 223 parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front()); 224 if (!ParsedFlagSet) 225 return ParsedFlagSet.takeError(); 226 SR.NewFlags = *ParsedFlagSet; 227 } 228 229 return SR; 230 } 231 232 static Expected<std::pair<StringRef, uint64_t>> 233 parseSetSectionAttribute(StringRef Option, StringRef FlagValue) { 234 if (!FlagValue.contains('=')) 235 return make_error<StringError>("bad format for " + Option + ": missing '='", 236 errc::invalid_argument); 237 auto Split = StringRef(FlagValue).split('='); 238 if (Split.first.empty()) 239 return make_error<StringError>("bad format for " + Option + 240 ": missing section name", 241 errc::invalid_argument); 242 uint64_t Value; 243 if (Split.second.getAsInteger(0, Value)) 244 return make_error<StringError>("invalid value for " + Option + ": '" + 245 Split.second + "'", 246 errc::invalid_argument); 247 return std::make_pair(Split.first, Value); 248 } 249 250 static Expected<SectionFlagsUpdate> 251 parseSetSectionFlagValue(StringRef FlagValue) { 252 if (!StringRef(FlagValue).contains('=')) 253 return createStringError(errc::invalid_argument, 254 "bad format for --set-section-flags: missing '='"); 255 256 // Initial split: ".foo" = "f1,f2,..." 257 auto Section2Flags = StringRef(FlagValue).split('='); 258 SectionFlagsUpdate SFU; 259 SFU.Name = Section2Flags.first; 260 261 // Flags split: "f1" "f2" ... 262 SmallVector<StringRef, 6> SectionFlags; 263 Section2Flags.second.split(SectionFlags, ','); 264 Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags); 265 if (!ParsedFlagSet) 266 return ParsedFlagSet.takeError(); 267 SFU.NewFlags = *ParsedFlagSet; 268 269 return SFU; 270 } 271 272 static Expected<uint8_t> parseVisibilityType(StringRef VisType) { 273 const uint8_t Invalid = 0xff; 274 uint8_t type = StringSwitch<uint8_t>(VisType) 275 .Case("default", ELF::STV_DEFAULT) 276 .Case("hidden", ELF::STV_HIDDEN) 277 .Case("internal", ELF::STV_INTERNAL) 278 .Case("protected", ELF::STV_PROTECTED) 279 .Default(Invalid); 280 if (type == Invalid) 281 return createStringError(errc::invalid_argument, 282 "'%s' is not a valid symbol visibility", 283 VisType.str().c_str()); 284 return type; 285 } 286 287 namespace { 288 struct TargetInfo { 289 FileFormat Format; 290 MachineInfo Machine; 291 }; 292 } // namespace 293 294 // FIXME: consolidate with the bfd parsing used by lld. 295 static const StringMap<MachineInfo> TargetMap{ 296 // Name, {EMachine, 64bit, LittleEndian} 297 // x86 298 {"elf32-i386", {ELF::EM_386, false, true}}, 299 {"elf32-x86-64", {ELF::EM_X86_64, false, true}}, 300 {"elf64-x86-64", {ELF::EM_X86_64, true, true}}, 301 // Intel MCU 302 {"elf32-iamcu", {ELF::EM_IAMCU, false, true}}, 303 // ARM 304 {"elf32-littlearm", {ELF::EM_ARM, false, true}}, 305 // ARM AArch64 306 {"elf64-aarch64", {ELF::EM_AARCH64, true, true}}, 307 {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}}, 308 // RISC-V 309 {"elf32-littleriscv", {ELF::EM_RISCV, false, true}}, 310 {"elf64-littleriscv", {ELF::EM_RISCV, true, true}}, 311 // PowerPC 312 {"elf32-powerpc", {ELF::EM_PPC, false, false}}, 313 {"elf32-powerpcle", {ELF::EM_PPC, false, true}}, 314 {"elf64-powerpc", {ELF::EM_PPC64, true, false}}, 315 {"elf64-powerpcle", {ELF::EM_PPC64, true, true}}, 316 // MIPS 317 {"elf32-bigmips", {ELF::EM_MIPS, false, false}}, 318 {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}}, 319 {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}}, 320 {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}}, 321 {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}}, 322 {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}}, 323 {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}}, 324 // SPARC 325 {"elf32-sparc", {ELF::EM_SPARC, false, false}}, 326 {"elf32-sparcel", {ELF::EM_SPARC, false, true}}, 327 // Hexagon 328 {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}}, 329 // LoongArch 330 {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}}, 331 {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}}, 332 // SystemZ 333 {"elf64-s390", {ELF::EM_S390, true, false}}, 334 }; 335 336 static Expected<TargetInfo> 337 getOutputTargetInfoByTargetName(StringRef TargetName) { 338 StringRef OriginalTargetName = TargetName; 339 bool IsFreeBSD = TargetName.consume_back("-freebsd"); 340 auto Iter = TargetMap.find(TargetName); 341 if (Iter == std::end(TargetMap)) 342 return createStringError(errc::invalid_argument, 343 "invalid output format: '%s'", 344 OriginalTargetName.str().c_str()); 345 MachineInfo MI = Iter->getValue(); 346 if (IsFreeBSD) 347 MI.OSABI = ELF::ELFOSABI_FREEBSD; 348 349 FileFormat Format; 350 if (TargetName.starts_with("elf")) 351 Format = FileFormat::ELF; 352 else 353 // This should never happen because `TargetName` is valid (it certainly 354 // exists in the TargetMap). 355 llvm_unreachable("unknown target prefix"); 356 357 return {TargetInfo{Format, MI}}; 358 } 359 360 static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc, 361 StringRef Filename, MatchStyle MS, 362 function_ref<Error(Error)> ErrorCallback) { 363 StringSaver Saver(Alloc); 364 SmallVector<StringRef, 16> Lines; 365 auto BufOrErr = MemoryBuffer::getFile(Filename); 366 if (!BufOrErr) 367 return createFileError(Filename, BufOrErr.getError()); 368 369 BufOrErr.get()->getBuffer().split(Lines, '\n'); 370 for (StringRef Line : Lines) { 371 // Ignore everything after '#', trim whitespace, and only add the symbol if 372 // it's not empty. 373 auto TrimmedLine = Line.split('#').first.trim(); 374 if (!TrimmedLine.empty()) 375 if (Error E = Symbols.addMatcher(NameOrPattern::create( 376 Saver.save(TrimmedLine), MS, ErrorCallback))) 377 return E; 378 } 379 380 return Error::success(); 381 } 382 383 static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename, 384 BumpPtrAllocator &Alloc, 385 StringRef Filename) { 386 StringSaver Saver(Alloc); 387 SmallVector<StringRef, 16> Lines; 388 auto BufOrErr = MemoryBuffer::getFile(Filename); 389 if (!BufOrErr) 390 return createFileError(Filename, BufOrErr.getError()); 391 392 BufOrErr.get()->getBuffer().split(Lines, '\n'); 393 size_t NumLines = Lines.size(); 394 for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) { 395 StringRef TrimmedLine = Lines[LineNo].split('#').first.trim(); 396 if (TrimmedLine.empty()) 397 continue; 398 399 std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' '); 400 StringRef NewName = Pair.second.trim(); 401 if (NewName.empty()) 402 return createStringError(errc::invalid_argument, 403 "%s:%zu: missing new symbol name", 404 Filename.str().c_str(), LineNo + 1); 405 SymbolsToRename.insert({Pair.first, NewName}); 406 } 407 return Error::success(); 408 } 409 410 template <class T> static ErrorOr<T> getAsInteger(StringRef Val) { 411 T Result; 412 if (Val.getAsInteger(0, Result)) 413 return errc::invalid_argument; 414 return Result; 415 } 416 417 namespace { 418 419 enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip }; 420 421 } // anonymous namespace 422 423 static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS, 424 ToolType Tool) { 425 StringRef HelpText, ToolName; 426 switch (Tool) { 427 case ToolType::Objcopy: 428 ToolName = "llvm-objcopy"; 429 HelpText = " [options] input [output]"; 430 break; 431 case ToolType::Strip: 432 ToolName = "llvm-strip"; 433 HelpText = " [options] inputs..."; 434 break; 435 case ToolType::InstallNameTool: 436 ToolName = "llvm-install-name-tool"; 437 HelpText = " [options] input"; 438 break; 439 case ToolType::BitcodeStrip: 440 ToolName = "llvm-bitcode-strip"; 441 HelpText = " [options] input"; 442 break; 443 } 444 OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(), 445 (ToolName + " tool").str().c_str()); 446 // TODO: Replace this with libOption call once it adds extrahelp support. 447 // The CommandLine library has a cl::extrahelp class to support this, 448 // but libOption does not have that yet. 449 OS << "\nPass @FILE as argument to read options from FILE.\n"; 450 } 451 452 static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) { 453 // Parse value given with --add-symbol option and create the 454 // new symbol if possible. The value format for --add-symbol is: 455 // 456 // <name>=[<section>:]<value>[,<flags>] 457 // 458 // where: 459 // <name> - symbol name, can be empty string 460 // <section> - optional section name. If not given ABS symbol is created 461 // <value> - symbol value, can be decimal or hexadecimal number prefixed 462 // with 0x. 463 // <flags> - optional flags affecting symbol type, binding or visibility. 464 NewSymbolInfo SI; 465 StringRef Value; 466 std::tie(SI.SymbolName, Value) = FlagValue.split('='); 467 if (Value.empty()) 468 return createStringError( 469 errc::invalid_argument, 470 "bad format for --add-symbol, missing '=' after '%s'", 471 SI.SymbolName.str().c_str()); 472 473 if (Value.contains(':')) { 474 std::tie(SI.SectionName, Value) = Value.split(':'); 475 if (SI.SectionName.empty() || Value.empty()) 476 return createStringError( 477 errc::invalid_argument, 478 "bad format for --add-symbol, missing section name or symbol value"); 479 } 480 481 SmallVector<StringRef, 6> Flags; 482 Value.split(Flags, ','); 483 if (Flags[0].getAsInteger(0, SI.Value)) 484 return createStringError(errc::invalid_argument, "bad symbol value: '%s'", 485 Flags[0].str().c_str()); 486 487 using Functor = std::function<void()>; 488 SmallVector<StringRef, 6> UnsupportedFlags; 489 for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I) 490 static_cast<Functor>( 491 StringSwitch<Functor>(Flags[I]) 492 .CaseLower("global", 493 [&] { SI.Flags.push_back(SymbolFlag::Global); }) 494 .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); }) 495 .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); }) 496 .CaseLower("default", 497 [&] { SI.Flags.push_back(SymbolFlag::Default); }) 498 .CaseLower("hidden", 499 [&] { SI.Flags.push_back(SymbolFlag::Hidden); }) 500 .CaseLower("protected", 501 [&] { SI.Flags.push_back(SymbolFlag::Protected); }) 502 .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); }) 503 .CaseLower("section", 504 [&] { SI.Flags.push_back(SymbolFlag::Section); }) 505 .CaseLower("object", 506 [&] { SI.Flags.push_back(SymbolFlag::Object); }) 507 .CaseLower("function", 508 [&] { SI.Flags.push_back(SymbolFlag::Function); }) 509 .CaseLower( 510 "indirect-function", 511 [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); }) 512 .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); }) 513 .CaseLower("constructor", 514 [&] { SI.Flags.push_back(SymbolFlag::Constructor); }) 515 .CaseLower("warning", 516 [&] { SI.Flags.push_back(SymbolFlag::Warning); }) 517 .CaseLower("indirect", 518 [&] { SI.Flags.push_back(SymbolFlag::Indirect); }) 519 .CaseLower("synthetic", 520 [&] { SI.Flags.push_back(SymbolFlag::Synthetic); }) 521 .CaseLower("unique-object", 522 [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); }) 523 .StartsWithLower("before=", 524 [&] { 525 StringRef SymNamePart = 526 Flags[I].split('=').second; 527 528 if (!SymNamePart.empty()) 529 SI.BeforeSyms.push_back(SymNamePart); 530 }) 531 .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))(); 532 if (!UnsupportedFlags.empty()) 533 return createStringError(errc::invalid_argument, 534 "unsupported flag%s for --add-symbol: '%s'", 535 UnsupportedFlags.size() > 1 ? "s" : "", 536 join(UnsupportedFlags, "', '").c_str()); 537 538 return SI; 539 } 540 541 static Expected<RemoveNoteInfo> parseRemoveNoteInfo(StringRef FlagValue) { 542 // Parse value given with --remove-note option. The format is: 543 // 544 // [name/]type_id 545 // 546 // where: 547 // <name> - optional note name. If not given, all notes with the specified 548 // <type_id> are removed. 549 // <type_id> - note type value, can be decimal or hexadecimal number prefixed 550 // with 0x. 551 RemoveNoteInfo NI; 552 StringRef TypeIdStr; 553 if (auto Idx = FlagValue.find('/'); Idx != StringRef::npos) { 554 if (Idx == 0) 555 return createStringError( 556 errc::invalid_argument, 557 "bad format for --remove-note, note name is empty"); 558 NI.Name = FlagValue.slice(0, Idx); 559 TypeIdStr = FlagValue.substr(Idx + 1); 560 } else { 561 TypeIdStr = FlagValue; 562 } 563 if (TypeIdStr.empty()) 564 return createStringError(errc::invalid_argument, 565 "bad format for --remove-note, missing type_id"); 566 if (TypeIdStr.getAsInteger(0, NI.TypeId)) 567 return createStringError(errc::invalid_argument, 568 "bad note type_id for --remove-note: '%s'", 569 TypeIdStr.str().c_str()); 570 return NI; 571 } 572 573 // Parse input option \p ArgValue and load section data. This function 574 // extracts section name and name of the file keeping section data from 575 // ArgValue, loads data from the file, and stores section name and data 576 // into the vector of new sections \p NewSections. 577 static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName, 578 SmallVector<NewSectionInfo, 0> &NewSections) { 579 if (!ArgValue.contains('=')) 580 return createStringError(errc::invalid_argument, 581 "bad format for " + OptionName + ": missing '='"); 582 583 std::pair<StringRef, StringRef> SecPair = ArgValue.split("="); 584 if (SecPair.second.empty()) 585 return createStringError(errc::invalid_argument, "bad format for " + 586 OptionName + 587 ": missing file name"); 588 589 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 590 MemoryBuffer::getFile(SecPair.second); 591 if (!BufOrErr) 592 return createFileError(SecPair.second, 593 errorCodeToError(BufOrErr.getError())); 594 595 NewSections.push_back({SecPair.first, std::move(*BufOrErr)}); 596 return Error::success(); 597 } 598 599 static Expected<int64_t> parseChangeSectionLMA(StringRef ArgValue, 600 StringRef OptionName) { 601 StringRef StringValue; 602 if (ArgValue.starts_with("*+")) { 603 StringValue = ArgValue.substr(2); 604 } else if (ArgValue.starts_with("*-")) { 605 StringValue = ArgValue.substr(1); 606 } else if (ArgValue.contains("=")) { 607 return createStringError(errc::invalid_argument, 608 "bad format for " + OptionName + 609 ": changing LMA to a specific value is not " 610 "supported. Use *+val or *-val instead"); 611 } else if (ArgValue.contains("+") || ArgValue.contains("-")) { 612 return createStringError(errc::invalid_argument, 613 "bad format for " + OptionName + 614 ": changing a specific section LMA is not " 615 "supported. Use *+val or *-val instead"); 616 } 617 if (StringValue.empty()) 618 return createStringError(errc::invalid_argument, 619 "bad format for " + OptionName + 620 ": missing LMA offset"); 621 622 auto LMAValue = getAsInteger<int64_t>(StringValue); 623 if (!LMAValue) 624 return createStringError(LMAValue.getError(), 625 "bad format for " + OptionName + ": value after " + 626 ArgValue.slice(0, 2) + " is " + StringValue + 627 " when it should be an integer"); 628 return *LMAValue; 629 } 630 631 static Expected<SectionPatternAddressUpdate> 632 parseChangeSectionAddr(StringRef ArgValue, StringRef OptionName, 633 MatchStyle SectionMatchStyle, 634 function_ref<Error(Error)> ErrorCallback) { 635 SectionPatternAddressUpdate PatternUpdate; 636 637 size_t LastSymbolIndex = ArgValue.find_last_of("+-="); 638 if (LastSymbolIndex == StringRef::npos) 639 return createStringError(errc::invalid_argument, 640 "bad format for " + OptionName + 641 ": argument value " + ArgValue + 642 " is invalid. See --help"); 643 char UpdateSymbol = ArgValue[LastSymbolIndex]; 644 645 StringRef SectionPattern = ArgValue.slice(0, LastSymbolIndex); 646 if (SectionPattern.empty()) 647 return createStringError( 648 errc::invalid_argument, 649 "bad format for " + OptionName + 650 ": missing section pattern to apply address change to"); 651 if (Error E = PatternUpdate.SectionPattern.addMatcher(NameOrPattern::create( 652 SectionPattern, SectionMatchStyle, ErrorCallback))) 653 return std::move(E); 654 655 StringRef Value = ArgValue.substr(LastSymbolIndex + 1); 656 if (Value.empty()) { 657 switch (UpdateSymbol) { 658 case '+': 659 case '-': 660 return createStringError(errc::invalid_argument, 661 "bad format for " + OptionName + 662 ": missing value of offset after '" + 663 std::string({UpdateSymbol}) + "'"); 664 665 case '=': 666 return createStringError(errc::invalid_argument, 667 "bad format for " + OptionName + 668 ": missing address value after '='"); 669 } 670 } 671 auto AddrValue = getAsInteger<uint64_t>(Value); 672 if (!AddrValue) 673 return createStringError(AddrValue.getError(), 674 "bad format for " + OptionName + ": value after " + 675 std::string({UpdateSymbol}) + " is " + Value + 676 " when it should be a 64-bit integer"); 677 678 switch (UpdateSymbol) { 679 case '+': 680 PatternUpdate.Update.Kind = AdjustKind::Add; 681 break; 682 case '-': 683 PatternUpdate.Update.Kind = AdjustKind::Subtract; 684 break; 685 case '=': 686 PatternUpdate.Update.Kind = AdjustKind::Set; 687 } 688 689 PatternUpdate.Update.Value = *AddrValue; 690 return PatternUpdate; 691 } 692 693 // parseObjcopyOptions returns the config and sets the input arguments. If a 694 // help flag is set then parseObjcopyOptions will print the help messege and 695 // exit. 696 Expected<DriverConfig> 697 objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr, 698 function_ref<Error(Error)> ErrorCallback) { 699 DriverConfig DC; 700 ObjcopyOptTable T; 701 702 unsigned MissingArgumentIndex, MissingArgumentCount; 703 llvm::opt::InputArgList InputArgs = 704 T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 705 706 if (MissingArgumentCount) 707 return createStringError( 708 errc::invalid_argument, 709 "argument to '%s' is missing (expected %d value(s))", 710 InputArgs.getArgString(MissingArgumentIndex), MissingArgumentCount); 711 712 if (InputArgs.size() == 0) { 713 printHelp(T, errs(), ToolType::Objcopy); 714 exit(1); 715 } 716 717 if (InputArgs.hasArg(OBJCOPY_help)) { 718 printHelp(T, outs(), ToolType::Objcopy); 719 exit(0); 720 } 721 722 if (InputArgs.hasArg(OBJCOPY_version)) { 723 outs() << "llvm-objcopy, compatible with GNU objcopy\n"; 724 cl::PrintVersionMessage(); 725 exit(0); 726 } 727 728 SmallVector<const char *, 2> Positional; 729 730 for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN)) 731 return createStringError(errc::invalid_argument, "unknown argument '%s'", 732 Arg->getAsString(InputArgs).c_str()); 733 734 for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT)) 735 Positional.push_back(Arg->getValue()); 736 737 if (Positional.empty()) 738 return createStringError(errc::invalid_argument, "no input file specified"); 739 740 if (Positional.size() > 2) 741 return createStringError(errc::invalid_argument, 742 "too many positional arguments"); 743 744 ConfigManager ConfigMgr; 745 CommonConfig &Config = ConfigMgr.Common; 746 COFFConfig &COFFConfig = ConfigMgr.COFF; 747 ELFConfig &ELFConfig = ConfigMgr.ELF; 748 MachOConfig &MachOConfig = ConfigMgr.MachO; 749 Config.InputFilename = Positional[0]; 750 Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1]; 751 if (InputArgs.hasArg(OBJCOPY_target) && 752 (InputArgs.hasArg(OBJCOPY_input_target) || 753 InputArgs.hasArg(OBJCOPY_output_target))) 754 return createStringError( 755 errc::invalid_argument, 756 "--target cannot be used with --input-target or --output-target"); 757 758 if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard)) 759 return createStringError(errc::invalid_argument, 760 "--regex and --wildcard are incompatible"); 761 762 MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex) 763 ? MatchStyle::Regex 764 : MatchStyle::Wildcard; 765 MatchStyle SymbolMatchStyle 766 = InputArgs.hasArg(OBJCOPY_regex) ? MatchStyle::Regex 767 : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard 768 : MatchStyle::Literal; 769 StringRef InputFormat, OutputFormat; 770 if (InputArgs.hasArg(OBJCOPY_target)) { 771 InputFormat = InputArgs.getLastArgValue(OBJCOPY_target); 772 OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target); 773 } else { 774 InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target); 775 OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target); 776 } 777 778 // FIXME: Currently, we ignore the target for non-binary/ihex formats 779 // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the 780 // format by llvm::object::createBinary regardless of the option value. 781 Config.InputFormat = StringSwitch<FileFormat>(InputFormat) 782 .Case("binary", FileFormat::Binary) 783 .Case("ihex", FileFormat::IHex) 784 .Default(FileFormat::Unspecified); 785 786 if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) { 787 const uint8_t Invalid = 0xff; 788 StringRef VisibilityStr = 789 InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility); 790 791 ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr) 792 .Case("default", ELF::STV_DEFAULT) 793 .Case("hidden", ELF::STV_HIDDEN) 794 .Case("internal", ELF::STV_INTERNAL) 795 .Case("protected", ELF::STV_PROTECTED) 796 .Default(Invalid); 797 798 if (ELFConfig.NewSymbolVisibility == Invalid) 799 return createStringError(errc::invalid_argument, 800 "'%s' is not a valid symbol visibility", 801 VisibilityStr.str().c_str()); 802 } 803 804 for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) { 805 StringRef Subsystem, Version; 806 std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':'); 807 COFFConfig.Subsystem = 808 StringSwitch<unsigned>(Subsystem.lower()) 809 .Case("boot_application", 810 COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) 811 .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI) 812 .Cases("efi_application", "efi-app", 813 COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION) 814 .Cases("efi_boot_service_driver", "efi-bsd", 815 COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) 816 .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM) 817 .Cases("efi_runtime_driver", "efi-rtd", 818 COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) 819 .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE) 820 .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI) 821 .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI) 822 .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN); 823 if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN) 824 return createStringError(errc::invalid_argument, 825 "'%s' is not a valid subsystem", 826 Subsystem.str().c_str()); 827 if (!Version.empty()) { 828 StringRef Major, Minor; 829 std::tie(Major, Minor) = Version.split('.'); 830 unsigned Number; 831 if (Major.getAsInteger(10, Number)) 832 return createStringError(errc::invalid_argument, 833 "'%s' is not a valid subsystem major version", 834 Major.str().c_str()); 835 COFFConfig.MajorSubsystemVersion = Number; 836 Number = 0; 837 if (!Minor.empty() && Minor.getAsInteger(10, Number)) 838 return createStringError(errc::invalid_argument, 839 "'%s' is not a valid subsystem minor version", 840 Minor.str().c_str()); 841 COFFConfig.MinorSubsystemVersion = Number; 842 } 843 } 844 845 Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat) 846 .Case("binary", FileFormat::Binary) 847 .Case("ihex", FileFormat::IHex) 848 .Case("srec", FileFormat::SREC) 849 .Default(FileFormat::Unspecified); 850 if (Config.OutputFormat == FileFormat::Unspecified) { 851 if (OutputFormat.empty()) { 852 Config.OutputFormat = Config.InputFormat; 853 } else { 854 Expected<TargetInfo> Target = 855 getOutputTargetInfoByTargetName(OutputFormat); 856 if (!Target) 857 return Target.takeError(); 858 Config.OutputFormat = Target->Format; 859 Config.OutputArch = Target->Machine; 860 } 861 } 862 863 if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) { 864 Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue()) 865 .Case("zlib", DebugCompressionType::Zlib) 866 .Case("zstd", DebugCompressionType::Zstd) 867 .Default(DebugCompressionType::None); 868 if (Config.CompressionType == DebugCompressionType::None) { 869 return createStringError( 870 errc::invalid_argument, 871 "invalid or unsupported --compress-debug-sections format: %s", 872 A->getValue()); 873 } 874 if (const char *Reason = compression::getReasonIfUnsupported( 875 compression::formatFor(Config.CompressionType))) 876 return createStringError(errc::invalid_argument, Reason); 877 } 878 879 for (const auto *A : InputArgs.filtered(OBJCOPY_compress_sections)) { 880 SmallVector<StringRef, 0> Fields; 881 StringRef(A->getValue()).split(Fields, '='); 882 if (Fields.size() != 2 || Fields[1].empty()) { 883 return createStringError( 884 errc::invalid_argument, 885 A->getSpelling() + 886 ": parse error, not 'section-glob=[none|zlib|zstd]'"); 887 } 888 889 auto Type = StringSwitch<DebugCompressionType>(Fields[1]) 890 .Case("zlib", DebugCompressionType::Zlib) 891 .Case("zstd", DebugCompressionType::Zstd) 892 .Default(DebugCompressionType::None); 893 if (Type == DebugCompressionType::None && Fields[1] != "none") { 894 return createStringError( 895 errc::invalid_argument, 896 "invalid or unsupported --compress-sections format: %s", 897 A->getValue()); 898 } 899 900 auto &P = Config.compressSections.emplace_back(); 901 P.second = Type; 902 auto Matcher = 903 NameOrPattern::create(Fields[0], SectionMatchStyle, ErrorCallback); 904 // =none allows overriding a previous =zlib or =zstd. Reject negative 905 // patterns, which would be confusing. 906 if (Matcher && !Matcher->isPositiveMatch()) { 907 return createStringError( 908 errc::invalid_argument, 909 "--compress-sections: negative pattern is unsupported"); 910 } 911 if (Error E = P.first.addMatcher(std::move(Matcher))) 912 return std::move(E); 913 } 914 915 Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); 916 // The gnu_debuglink's target is expected to not change or else its CRC would 917 // become invalidated and get rejected. We can avoid recalculating the 918 // checksum for every target file inside an archive by precomputing the CRC 919 // here. This prevents a significant amount of I/O. 920 if (!Config.AddGnuDebugLink.empty()) { 921 auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink); 922 if (!DebugOrErr) 923 return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError()); 924 auto Debug = std::move(*DebugOrErr); 925 Config.GnuDebugLinkCRC32 = 926 llvm::crc32(arrayRefFromStringRef(Debug->getBuffer())); 927 } 928 Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); 929 930 Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols); 931 Config.SymbolsPrefixRemove = 932 InputArgs.getLastArgValue(OBJCOPY_remove_symbol_prefix); 933 934 Config.AllocSectionsPrefix = 935 InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections); 936 if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition)) 937 Config.ExtractPartition = Arg->getValue(); 938 939 if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) { 940 if (Config.OutputFormat != FileFormat::Binary) 941 return createStringError( 942 errc::invalid_argument, 943 "'--gap-fill' is only supported for binary output"); 944 ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue()); 945 if (!Val) 946 return createStringError(Val.getError(), "--gap-fill: bad number: %s", 947 A->getValue()); 948 uint8_t ByteVal = Val.get(); 949 if (ByteVal != Val.get()) 950 return createStringError(std::errc::value_too_large, 951 "gap-fill value %s is out of range (0 to 0xff)", 952 A->getValue()); 953 Config.GapFill = ByteVal; 954 } 955 956 if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) { 957 if (Config.OutputFormat != FileFormat::Binary) 958 return createStringError( 959 errc::invalid_argument, 960 "'--pad-to' is only supported for binary output"); 961 ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue()); 962 if (!Addr) 963 return createStringError(Addr.getError(), "--pad-to: bad number: %s", 964 A->getValue()); 965 Config.PadTo = *Addr; 966 } 967 968 if (const auto *Arg = InputArgs.getLastArg(OBJCOPY_change_section_lma)) { 969 Expected<int64_t> LMAValue = 970 parseChangeSectionLMA(Arg->getValue(), Arg->getSpelling()); 971 if (!LMAValue) 972 return LMAValue.takeError(); 973 Config.ChangeSectionLMAValAll = *LMAValue; 974 } 975 976 for (auto *Arg : InputArgs.filtered(OBJCOPY_change_section_address)) { 977 Expected<SectionPatternAddressUpdate> AddressUpdate = 978 parseChangeSectionAddr(Arg->getValue(), Arg->getSpelling(), 979 SectionMatchStyle, ErrorCallback); 980 if (!AddressUpdate) 981 return AddressUpdate.takeError(); 982 Config.ChangeSectionAddress.push_back(*AddressUpdate); 983 } 984 985 for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) { 986 if (!StringRef(Arg->getValue()).contains('=')) 987 return createStringError(errc::invalid_argument, 988 "bad format for --redefine-sym"); 989 auto Old2New = StringRef(Arg->getValue()).split('='); 990 if (!Config.SymbolsToRename.insert(Old2New).second) 991 return createStringError(errc::invalid_argument, 992 "multiple redefinition of symbol '%s'", 993 Old2New.first.str().c_str()); 994 } 995 996 for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols)) 997 if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc, 998 Arg->getValue())) 999 return std::move(E); 1000 1001 for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) { 1002 Expected<SectionRename> SR = 1003 parseRenameSectionValue(StringRef(Arg->getValue())); 1004 if (!SR) 1005 return SR.takeError(); 1006 if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second) 1007 return createStringError(errc::invalid_argument, 1008 "multiple renames of section '%s'", 1009 SR->OriginalName.str().c_str()); 1010 } 1011 for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) { 1012 Expected<std::pair<StringRef, uint64_t>> NameAndAlign = 1013 parseSetSectionAttribute("--set-section-alignment", Arg->getValue()); 1014 if (!NameAndAlign) 1015 return NameAndAlign.takeError(); 1016 Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second; 1017 } 1018 for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) { 1019 Expected<SectionFlagsUpdate> SFU = 1020 parseSetSectionFlagValue(Arg->getValue()); 1021 if (!SFU) 1022 return SFU.takeError(); 1023 if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second) 1024 return createStringError( 1025 errc::invalid_argument, 1026 "--set-section-flags set multiple times for section '%s'", 1027 SFU->Name.str().c_str()); 1028 } 1029 for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) { 1030 Expected<std::pair<StringRef, uint64_t>> NameAndType = 1031 parseSetSectionAttribute("--set-section-type", Arg->getValue()); 1032 if (!NameAndType) 1033 return NameAndType.takeError(); 1034 Config.SetSectionType[NameAndType->first] = NameAndType->second; 1035 } 1036 // Prohibit combinations of --set-section-{flags,type} when the section name 1037 // is used as the destination of a --rename-section. 1038 for (const auto &E : Config.SectionsToRename) { 1039 const SectionRename &SR = E.second; 1040 auto Err = [&](const char *Option) { 1041 return createStringError( 1042 errc::invalid_argument, 1043 "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option, 1044 SR.NewName.str().c_str(), SR.OriginalName.str().c_str(), 1045 SR.NewName.str().c_str()); 1046 }; 1047 if (Config.SetSectionFlags.count(SR.NewName)) 1048 return Err("flags"); 1049 if (Config.SetSectionType.count(SR.NewName)) 1050 return Err("type"); 1051 } 1052 1053 for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section)) 1054 if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( 1055 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1056 return std::move(E); 1057 for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section)) 1058 if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( 1059 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1060 return std::move(E); 1061 for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section)) 1062 if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create( 1063 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1064 return std::move(E); 1065 for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) { 1066 if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section", 1067 Config.AddSection)) 1068 return std::move(Err); 1069 } 1070 for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) { 1071 if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section", 1072 Config.UpdateSection)) 1073 return std::move(Err); 1074 } 1075 for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) { 1076 StringRef Value(Arg->getValue()); 1077 if (Value.split('=').second.empty()) 1078 return createStringError( 1079 errc::invalid_argument, 1080 "bad format for --dump-section, expected section=file"); 1081 Config.DumpSection.push_back(Value); 1082 } 1083 Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all); 1084 Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu); 1085 Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug); 1086 Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo); 1087 Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections); 1088 Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc); 1089 Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded); 1090 Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo); 1091 Config.ExtractMainPartition = 1092 InputArgs.hasArg(OBJCOPY_extract_main_partition); 1093 ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden); 1094 Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken); 1095 if (auto *Arg = 1096 InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) { 1097 Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all) 1098 ? DiscardType::All 1099 : DiscardType::Locals; 1100 } 1101 1102 ELFConfig.VerifyNoteSections = InputArgs.hasFlag( 1103 OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true); 1104 1105 Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug); 1106 ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols); 1107 MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined); 1108 Config.DecompressDebugSections = 1109 InputArgs.hasArg(OBJCOPY_decompress_debug_sections); 1110 if (Config.DiscardMode == DiscardType::All) { 1111 Config.StripDebug = true; 1112 ELFConfig.KeepFileSymbols = true; 1113 } 1114 for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol)) 1115 if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create( 1116 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1117 return std::move(E); 1118 for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols)) 1119 if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc, 1120 Arg->getValue(), SymbolMatchStyle, 1121 ErrorCallback)) 1122 return std::move(E); 1123 for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol)) 1124 if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create( 1125 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1126 return std::move(E); 1127 for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols)) 1128 if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc, 1129 Arg->getValue(), SymbolMatchStyle, 1130 ErrorCallback)) 1131 return std::move(E); 1132 for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol)) 1133 if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create( 1134 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1135 return std::move(E); 1136 for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols)) 1137 if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc, 1138 Arg->getValue(), SymbolMatchStyle, 1139 ErrorCallback)) 1140 return std::move(E); 1141 for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol)) 1142 if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create( 1143 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1144 return std::move(E); 1145 for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols)) 1146 if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc, 1147 Arg->getValue(), SymbolMatchStyle, 1148 ErrorCallback)) 1149 return std::move(E); 1150 for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol)) 1151 if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( 1152 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1153 return std::move(E); 1154 for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols)) 1155 if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc, 1156 Arg->getValue(), SymbolMatchStyle, 1157 ErrorCallback)) 1158 return std::move(E); 1159 for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol)) 1160 if (Error E = 1161 Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create( 1162 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1163 return std::move(E); 1164 for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols)) 1165 if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc, 1166 Arg->getValue(), SymbolMatchStyle, 1167 ErrorCallback)) 1168 return std::move(E); 1169 for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol)) 1170 if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create( 1171 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1172 return std::move(E); 1173 for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols)) 1174 if (Error E = 1175 addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(), 1176 SymbolMatchStyle, ErrorCallback)) 1177 return std::move(E); 1178 for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol)) 1179 if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create( 1180 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1181 return std::move(E); 1182 for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols)) 1183 if (Error E = 1184 addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(), 1185 SymbolMatchStyle, ErrorCallback)) 1186 return std::move(E); 1187 for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) { 1188 Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue()); 1189 if (!SymInfo) 1190 return SymInfo.takeError(); 1191 1192 Config.SymbolsToAdd.push_back(*SymInfo); 1193 } 1194 for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbol_visibility)) { 1195 if (!StringRef(Arg->getValue()).contains('=')) 1196 return createStringError(errc::invalid_argument, 1197 "bad format for --set-symbol-visibility"); 1198 auto [Sym, Visibility] = StringRef(Arg->getValue()).split('='); 1199 Expected<uint8_t> Type = parseVisibilityType(Visibility); 1200 if (!Type) 1201 return Type.takeError(); 1202 ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type); 1203 if (Error E = ELFConfig.SymbolsToSetVisibility.back().first.addMatcher( 1204 NameOrPattern::create(Sym, SymbolMatchStyle, ErrorCallback))) 1205 return std::move(E); 1206 } 1207 for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbols_visibility)) { 1208 if (!StringRef(Arg->getValue()).contains('=')) 1209 return createStringError(errc::invalid_argument, 1210 "bad format for --set-symbols-visibility"); 1211 auto [File, Visibility] = StringRef(Arg->getValue()).split('='); 1212 Expected<uint8_t> Type = parseVisibilityType(Visibility); 1213 if (!Type) 1214 return Type.takeError(); 1215 ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type); 1216 if (Error E = 1217 addSymbolsFromFile(ELFConfig.SymbolsToSetVisibility.back().first, 1218 DC.Alloc, File, SymbolMatchStyle, ErrorCallback)) 1219 return std::move(E); 1220 } 1221 1222 ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links); 1223 1224 Config.DeterministicArchives = InputArgs.hasFlag( 1225 OBJCOPY_enable_deterministic_archives, 1226 OBJCOPY_disable_deterministic_archives, /*default=*/true); 1227 1228 Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates); 1229 1230 if (Config.PreserveDates && 1231 (Config.OutputFilename == "-" || Config.InputFilename == "-")) 1232 return createStringError(errc::invalid_argument, 1233 "--preserve-dates requires a file"); 1234 1235 for (auto *Arg : InputArgs) 1236 if (Arg->getOption().matches(OBJCOPY_set_start)) { 1237 auto EAddr = getAsInteger<uint64_t>(Arg->getValue()); 1238 if (!EAddr) 1239 return createStringError( 1240 EAddr.getError(), "bad entry point address: '%s'", Arg->getValue()); 1241 1242 ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; }; 1243 } else if (Arg->getOption().matches(OBJCOPY_change_start)) { 1244 auto EIncr = getAsInteger<int64_t>(Arg->getValue()); 1245 if (!EIncr) 1246 return createStringError(EIncr.getError(), 1247 "bad entry point increment: '%s'", 1248 Arg->getValue()); 1249 auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr) 1250 : [](uint64_t A) { return A; }; 1251 ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) { 1252 return Expr(EAddr) + *EIncr; 1253 }; 1254 } 1255 1256 for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_note)) { 1257 Expected<RemoveNoteInfo> NoteInfo = parseRemoveNoteInfo(Arg->getValue()); 1258 if (!NoteInfo) 1259 return NoteInfo.takeError(); 1260 1261 ELFConfig.NotesToRemove.push_back(*NoteInfo); 1262 } 1263 1264 if (!ELFConfig.NotesToRemove.empty()) { 1265 if (!Config.ToRemove.empty()) 1266 return createStringError( 1267 errc::invalid_argument, 1268 "cannot specify both --remove-note and --remove-section"); 1269 if (!Config.AddSection.empty()) 1270 return createStringError( 1271 errc::invalid_argument, 1272 "cannot specify both --remove-note and --add-section"); 1273 if (!Config.UpdateSection.empty()) 1274 return createStringError( 1275 errc::invalid_argument, 1276 "cannot specify both --remove-note and --update-section"); 1277 } 1278 1279 if (Config.DecompressDebugSections && 1280 Config.CompressionType != DebugCompressionType::None) { 1281 return createStringError( 1282 errc::invalid_argument, 1283 "cannot specify both --compress-debug-sections and " 1284 "--decompress-debug-sections"); 1285 } 1286 1287 if (Config.ExtractPartition && Config.ExtractMainPartition) 1288 return createStringError(errc::invalid_argument, 1289 "cannot specify --extract-partition together with " 1290 "--extract-main-partition"); 1291 1292 DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1293 return std::move(DC); 1294 } 1295 1296 // parseInstallNameToolOptions returns the config and sets the input arguments. 1297 // If a help flag is set then parseInstallNameToolOptions will print the help 1298 // messege and exit. 1299 Expected<DriverConfig> 1300 objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) { 1301 DriverConfig DC; 1302 ConfigManager ConfigMgr; 1303 CommonConfig &Config = ConfigMgr.Common; 1304 MachOConfig &MachOConfig = ConfigMgr.MachO; 1305 InstallNameToolOptTable T; 1306 unsigned MissingArgumentIndex, MissingArgumentCount; 1307 llvm::opt::InputArgList InputArgs = 1308 T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1309 1310 if (MissingArgumentCount) 1311 return createStringError( 1312 errc::invalid_argument, 1313 "missing argument to " + 1314 StringRef(InputArgs.getArgString(MissingArgumentIndex)) + 1315 " option"); 1316 1317 if (InputArgs.size() == 0) { 1318 printHelp(T, errs(), ToolType::InstallNameTool); 1319 exit(1); 1320 } 1321 1322 if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) { 1323 printHelp(T, outs(), ToolType::InstallNameTool); 1324 exit(0); 1325 } 1326 1327 if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) { 1328 outs() << "llvm-install-name-tool, compatible with cctools " 1329 "install_name_tool\n"; 1330 cl::PrintVersionMessage(); 1331 exit(0); 1332 } 1333 1334 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath)) 1335 MachOConfig.RPathToAdd.push_back(Arg->getValue()); 1336 1337 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath)) 1338 MachOConfig.RPathToPrepend.push_back(Arg->getValue()); 1339 1340 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) { 1341 StringRef RPath = Arg->getValue(); 1342 1343 // Cannot add and delete the same rpath at the same time. 1344 if (is_contained(MachOConfig.RPathToAdd, RPath)) 1345 return createStringError( 1346 errc::invalid_argument, 1347 "cannot specify both -add_rpath '%s' and -delete_rpath '%s'", 1348 RPath.str().c_str(), RPath.str().c_str()); 1349 if (is_contained(MachOConfig.RPathToPrepend, RPath)) 1350 return createStringError( 1351 errc::invalid_argument, 1352 "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'", 1353 RPath.str().c_str(), RPath.str().c_str()); 1354 1355 MachOConfig.RPathsToRemove.insert(RPath); 1356 } 1357 1358 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) { 1359 StringRef Old = Arg->getValue(0); 1360 StringRef New = Arg->getValue(1); 1361 1362 auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; }; 1363 1364 // Cannot specify duplicate -rpath entries 1365 auto It1 = find_if( 1366 MachOConfig.RPathsToUpdate, 1367 [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) { 1368 return Match(OldNew.getFirst()) || Match(OldNew.getSecond()); 1369 }); 1370 if (It1 != MachOConfig.RPathsToUpdate.end()) 1371 return createStringError(errc::invalid_argument, 1372 "cannot specify both -rpath '" + 1373 It1->getFirst() + "' '" + It1->getSecond() + 1374 "' and -rpath '" + Old + "' '" + New + "'"); 1375 1376 // Cannot specify the same rpath under both -delete_rpath and -rpath 1377 auto It2 = find_if(MachOConfig.RPathsToRemove, Match); 1378 if (It2 != MachOConfig.RPathsToRemove.end()) 1379 return createStringError(errc::invalid_argument, 1380 "cannot specify both -delete_rpath '" + *It2 + 1381 "' and -rpath '" + Old + "' '" + New + "'"); 1382 1383 // Cannot specify the same rpath under both -add_rpath and -rpath 1384 auto It3 = find_if(MachOConfig.RPathToAdd, Match); 1385 if (It3 != MachOConfig.RPathToAdd.end()) 1386 return createStringError(errc::invalid_argument, 1387 "cannot specify both -add_rpath '" + *It3 + 1388 "' and -rpath '" + Old + "' '" + New + "'"); 1389 1390 // Cannot specify the same rpath under both -prepend_rpath and -rpath. 1391 auto It4 = find_if(MachOConfig.RPathToPrepend, Match); 1392 if (It4 != MachOConfig.RPathToPrepend.end()) 1393 return createStringError(errc::invalid_argument, 1394 "cannot specify both -prepend_rpath '" + *It4 + 1395 "' and -rpath '" + Old + "' '" + New + "'"); 1396 1397 MachOConfig.RPathsToUpdate.insert({Old, New}); 1398 } 1399 1400 if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) { 1401 MachOConfig.SharedLibId = Arg->getValue(); 1402 if (MachOConfig.SharedLibId->empty()) 1403 return createStringError(errc::invalid_argument, 1404 "cannot specify an empty id"); 1405 } 1406 1407 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change)) 1408 MachOConfig.InstallNamesToUpdate.insert( 1409 {Arg->getValue(0), Arg->getValue(1)}); 1410 1411 MachOConfig.RemoveAllRpaths = 1412 InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths); 1413 1414 SmallVector<StringRef, 2> Positional; 1415 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN)) 1416 return createStringError(errc::invalid_argument, "unknown argument '%s'", 1417 Arg->getAsString(InputArgs).c_str()); 1418 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT)) 1419 Positional.push_back(Arg->getValue()); 1420 if (Positional.empty()) 1421 return createStringError(errc::invalid_argument, "no input file specified"); 1422 if (Positional.size() > 1) 1423 return createStringError( 1424 errc::invalid_argument, 1425 "llvm-install-name-tool expects a single input file"); 1426 Config.InputFilename = Positional[0]; 1427 Config.OutputFilename = Positional[0]; 1428 1429 Expected<OwningBinary<Binary>> BinaryOrErr = 1430 createBinary(Config.InputFilename); 1431 if (!BinaryOrErr) 1432 return createFileError(Config.InputFilename, BinaryOrErr.takeError()); 1433 auto *Binary = (*BinaryOrErr).getBinary(); 1434 if (!Binary->isMachO() && !Binary->isMachOUniversalBinary()) 1435 return createStringError(errc::invalid_argument, 1436 "input file: %s is not a Mach-O file", 1437 Config.InputFilename.str().c_str()); 1438 1439 DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1440 return std::move(DC); 1441 } 1442 1443 Expected<DriverConfig> 1444 objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr, 1445 function_ref<Error(Error)> ErrorCallback) { 1446 DriverConfig DC; 1447 ConfigManager ConfigMgr; 1448 CommonConfig &Config = ConfigMgr.Common; 1449 MachOConfig &MachOConfig = ConfigMgr.MachO; 1450 BitcodeStripOptTable T; 1451 unsigned MissingArgumentIndex, MissingArgumentCount; 1452 opt::InputArgList InputArgs = 1453 T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1454 1455 if (InputArgs.size() == 0) { 1456 printHelp(T, errs(), ToolType::BitcodeStrip); 1457 exit(1); 1458 } 1459 1460 if (InputArgs.hasArg(BITCODE_STRIP_help)) { 1461 printHelp(T, outs(), ToolType::BitcodeStrip); 1462 exit(0); 1463 } 1464 1465 if (InputArgs.hasArg(BITCODE_STRIP_version)) { 1466 outs() << "llvm-bitcode-strip, compatible with cctools " 1467 "bitcode_strip\n"; 1468 cl::PrintVersionMessage(); 1469 exit(0); 1470 } 1471 1472 for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN)) 1473 return createStringError(errc::invalid_argument, "unknown argument '%s'", 1474 Arg->getAsString(InputArgs).c_str()); 1475 1476 SmallVector<StringRef, 2> Positional; 1477 for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT)) 1478 Positional.push_back(Arg->getValue()); 1479 if (Positional.size() > 1) 1480 return createStringError(errc::invalid_argument, 1481 "llvm-bitcode-strip expects a single input file"); 1482 assert(!Positional.empty()); 1483 Config.InputFilename = Positional[0]; 1484 1485 if (!InputArgs.hasArg(BITCODE_STRIP_output)) { 1486 return createStringError(errc::invalid_argument, 1487 "-o is a required argument"); 1488 } 1489 Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output); 1490 1491 if (!InputArgs.hasArg(BITCODE_STRIP_remove)) 1492 return createStringError(errc::invalid_argument, "no action specified"); 1493 1494 // We only support -r for now, which removes all bitcode sections and 1495 // the __LLVM segment if it's now empty. 1496 cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1497 "__LLVM,__asm", MatchStyle::Literal, ErrorCallback))); 1498 cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1499 "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback))); 1500 cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1501 "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback))); 1502 cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1503 "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback))); 1504 cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1505 "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback))); 1506 MachOConfig.EmptySegmentsToRemove.insert("__LLVM"); 1507 1508 DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1509 return std::move(DC); 1510 } 1511 1512 // parseStripOptions returns the config and sets the input arguments. If a 1513 // help flag is set then parseStripOptions will print the help messege and 1514 // exit. 1515 Expected<DriverConfig> 1516 objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr, 1517 function_ref<Error(Error)> ErrorCallback) { 1518 const char *const *DashDash = 1519 llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; }); 1520 ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash); 1521 if (DashDash != RawArgsArr.end()) 1522 DashDash = std::next(DashDash); 1523 1524 StripOptTable T; 1525 unsigned MissingArgumentIndex, MissingArgumentCount; 1526 llvm::opt::InputArgList InputArgs = 1527 T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1528 1529 if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) { 1530 printHelp(T, errs(), ToolType::Strip); 1531 exit(1); 1532 } 1533 1534 if (InputArgs.hasArg(STRIP_help)) { 1535 printHelp(T, outs(), ToolType::Strip); 1536 exit(0); 1537 } 1538 1539 if (InputArgs.hasArg(STRIP_version)) { 1540 outs() << "llvm-strip, compatible with GNU strip\n"; 1541 cl::PrintVersionMessage(); 1542 exit(0); 1543 } 1544 1545 SmallVector<StringRef, 2> Positional; 1546 for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN)) 1547 return createStringError(errc::invalid_argument, "unknown argument '%s'", 1548 Arg->getAsString(InputArgs).c_str()); 1549 for (auto *Arg : InputArgs.filtered(STRIP_INPUT)) 1550 Positional.push_back(Arg->getValue()); 1551 std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional)); 1552 1553 if (Positional.empty()) 1554 return createStringError(errc::invalid_argument, "no input file specified"); 1555 1556 if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output)) 1557 return createStringError( 1558 errc::invalid_argument, 1559 "multiple input files cannot be used in combination with -o"); 1560 1561 ConfigManager ConfigMgr; 1562 CommonConfig &Config = ConfigMgr.Common; 1563 ELFConfig &ELFConfig = ConfigMgr.ELF; 1564 MachOConfig &MachOConfig = ConfigMgr.MachO; 1565 1566 if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard)) 1567 return createStringError(errc::invalid_argument, 1568 "--regex and --wildcard are incompatible"); 1569 MatchStyle SectionMatchStyle = 1570 InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard; 1571 MatchStyle SymbolMatchStyle 1572 = InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex 1573 : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard 1574 : MatchStyle::Literal; 1575 ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links); 1576 Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug); 1577 1578 if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals)) 1579 Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all) 1580 ? DiscardType::All 1581 : DiscardType::Locals; 1582 Config.StripSections = InputArgs.hasArg(STRIP_strip_sections); 1583 Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded); 1584 if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all)) 1585 Config.StripAll = Arg->getOption().getID() == STRIP_strip_all; 1586 Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu); 1587 MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols); 1588 Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug); 1589 ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols); 1590 MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined); 1591 1592 for (auto *Arg : InputArgs.filtered(STRIP_keep_section)) 1593 if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( 1594 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1595 return std::move(E); 1596 1597 for (auto *Arg : InputArgs.filtered(STRIP_remove_section)) 1598 if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( 1599 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1600 return std::move(E); 1601 1602 for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol)) 1603 if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( 1604 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1605 return std::move(E); 1606 1607 for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol)) 1608 if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create( 1609 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1610 return std::move(E); 1611 1612 if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug && 1613 !Config.OnlyKeepDebug && !Config.StripUnneeded && 1614 Config.DiscardMode == DiscardType::None && !Config.StripAllGNU && 1615 Config.SymbolsToRemove.empty()) 1616 Config.StripAll = true; 1617 1618 if (Config.DiscardMode == DiscardType::All) { 1619 Config.StripDebug = true; 1620 ELFConfig.KeepFileSymbols = true; 1621 } 1622 1623 Config.DeterministicArchives = 1624 InputArgs.hasFlag(STRIP_enable_deterministic_archives, 1625 STRIP_disable_deterministic_archives, /*default=*/true); 1626 1627 Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates); 1628 Config.InputFormat = FileFormat::Unspecified; 1629 Config.OutputFormat = FileFormat::Unspecified; 1630 1631 DriverConfig DC; 1632 if (Positional.size() == 1) { 1633 Config.InputFilename = Positional[0]; 1634 Config.OutputFilename = 1635 InputArgs.getLastArgValue(STRIP_output, Positional[0]); 1636 DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1637 } else { 1638 StringMap<unsigned> InputFiles; 1639 for (StringRef Filename : Positional) { 1640 if (InputFiles[Filename]++ == 1) { 1641 if (Filename == "-") 1642 return createStringError( 1643 errc::invalid_argument, 1644 "cannot specify '-' as an input file more than once"); 1645 if (Error E = ErrorCallback(createStringError( 1646 errc::invalid_argument, "'%s' was already specified", 1647 Filename.str().c_str()))) 1648 return std::move(E); 1649 } 1650 Config.InputFilename = Filename; 1651 Config.OutputFilename = Filename; 1652 DC.CopyConfigs.push_back(ConfigMgr); 1653 } 1654 } 1655 1656 if (Config.PreserveDates && (is_contained(Positional, "-") || 1657 InputArgs.getLastArgValue(STRIP_output) == "-")) 1658 return createStringError(errc::invalid_argument, 1659 "--preserve-dates requires a file"); 1660 1661 return std::move(DC); 1662 } 1663