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