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