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