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 (auto Arg = InputArgs.getLastArg(OBJCOPY_compress_debug_sections, 723 OBJCOPY_compress_debug_sections_eq)) { 724 Config.CompressionType = DebugCompressionType::Z; 725 726 if (Arg->getOption().getID() == OBJCOPY_compress_debug_sections_eq) { 727 Config.CompressionType = 728 StringSwitch<DebugCompressionType>( 729 InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq)) 730 .Case("zlib", DebugCompressionType::Z) 731 .Default(DebugCompressionType::None); 732 if (Config.CompressionType == DebugCompressionType::None) 733 return createStringError( 734 errc::invalid_argument, 735 "invalid or unsupported --compress-debug-sections format: %s", 736 InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq) 737 .str() 738 .c_str()); 739 } 740 if (!compression::zlib::isAvailable()) 741 return createStringError( 742 errc::invalid_argument, 743 "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress"); 744 } 745 746 Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); 747 // The gnu_debuglink's target is expected to not change or else its CRC would 748 // become invalidated and get rejected. We can avoid recalculating the 749 // checksum for every target file inside an archive by precomputing the CRC 750 // here. This prevents a significant amount of I/O. 751 if (!Config.AddGnuDebugLink.empty()) { 752 auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink); 753 if (!DebugOrErr) 754 return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError()); 755 auto Debug = std::move(*DebugOrErr); 756 Config.GnuDebugLinkCRC32 = 757 llvm::crc32(arrayRefFromStringRef(Debug->getBuffer())); 758 } 759 Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); 760 Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols); 761 Config.AllocSectionsPrefix = 762 InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections); 763 if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition)) 764 Config.ExtractPartition = Arg->getValue(); 765 766 for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) { 767 if (!StringRef(Arg->getValue()).contains('=')) 768 return createStringError(errc::invalid_argument, 769 "bad format for --redefine-sym"); 770 auto Old2New = StringRef(Arg->getValue()).split('='); 771 if (!Config.SymbolsToRename.insert(Old2New).second) 772 return createStringError(errc::invalid_argument, 773 "multiple redefinition of symbol '%s'", 774 Old2New.first.str().c_str()); 775 } 776 777 for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbols)) 778 if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc, 779 Arg->getValue())) 780 return std::move(E); 781 782 for (auto Arg : InputArgs.filtered(OBJCOPY_rename_section)) { 783 Expected<SectionRename> SR = 784 parseRenameSectionValue(StringRef(Arg->getValue())); 785 if (!SR) 786 return SR.takeError(); 787 if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second) 788 return createStringError(errc::invalid_argument, 789 "multiple renames of section '%s'", 790 SR->OriginalName.str().c_str()); 791 } 792 for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) { 793 Expected<std::pair<StringRef, uint64_t>> NameAndAlign = 794 parseSetSectionAttribute("--set-section-alignment", Arg->getValue()); 795 if (!NameAndAlign) 796 return NameAndAlign.takeError(); 797 Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second; 798 } 799 for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) { 800 Expected<SectionFlagsUpdate> SFU = 801 parseSetSectionFlagValue(Arg->getValue()); 802 if (!SFU) 803 return SFU.takeError(); 804 if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second) 805 return createStringError( 806 errc::invalid_argument, 807 "--set-section-flags set multiple times for section '%s'", 808 SFU->Name.str().c_str()); 809 } 810 for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_type)) { 811 Expected<std::pair<StringRef, uint64_t>> NameAndType = 812 parseSetSectionAttribute("--set-section-type", Arg->getValue()); 813 if (!NameAndType) 814 return NameAndType.takeError(); 815 Config.SetSectionType[NameAndType->first] = NameAndType->second; 816 } 817 // Prohibit combinations of --set-section-{flags,type} when the section name 818 // is used as the destination of a --rename-section. 819 for (const auto &E : Config.SectionsToRename) { 820 const SectionRename &SR = E.second; 821 auto Err = [&](const char *Option) { 822 return createStringError( 823 errc::invalid_argument, 824 "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option, 825 SR.NewName.str().c_str(), SR.OriginalName.str().c_str(), 826 SR.NewName.str().c_str()); 827 }; 828 if (Config.SetSectionFlags.count(SR.NewName)) 829 return Err("flags"); 830 if (Config.SetSectionType.count(SR.NewName)) 831 return Err("type"); 832 } 833 834 for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section)) 835 if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( 836 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 837 return std::move(E); 838 for (auto Arg : InputArgs.filtered(OBJCOPY_keep_section)) 839 if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( 840 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 841 return std::move(E); 842 for (auto Arg : InputArgs.filtered(OBJCOPY_only_section)) 843 if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create( 844 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 845 return std::move(E); 846 for (auto Arg : InputArgs.filtered(OBJCOPY_add_section)) { 847 if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section", 848 Config.AddSection)) 849 return std::move(Err); 850 } 851 for (auto Arg : InputArgs.filtered(OBJCOPY_update_section)) { 852 if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section", 853 Config.UpdateSection)) 854 return std::move(Err); 855 } 856 for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) { 857 StringRef Value(Arg->getValue()); 858 if (Value.split('=').second.empty()) 859 return createStringError( 860 errc::invalid_argument, 861 "bad format for --dump-section, expected section=file"); 862 Config.DumpSection.push_back(Value); 863 } 864 Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all); 865 Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu); 866 Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug); 867 Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo); 868 Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections); 869 Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc); 870 Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded); 871 Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo); 872 Config.ExtractMainPartition = 873 InputArgs.hasArg(OBJCOPY_extract_main_partition); 874 ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden); 875 Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken); 876 if (auto *Arg = 877 InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) { 878 Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all) 879 ? DiscardType::All 880 : DiscardType::Locals; 881 } 882 Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug); 883 ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols); 884 MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined); 885 Config.DecompressDebugSections = 886 InputArgs.hasArg(OBJCOPY_decompress_debug_sections); 887 if (Config.DiscardMode == DiscardType::All) { 888 Config.StripDebug = true; 889 ELFConfig.KeepFileSymbols = true; 890 } 891 for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol)) 892 if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create( 893 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 894 return std::move(E); 895 for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbols)) 896 if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc, 897 Arg->getValue(), SymbolMatchStyle, 898 ErrorCallback)) 899 return std::move(E); 900 for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol)) 901 if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create( 902 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 903 return std::move(E); 904 for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols)) 905 if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc, 906 Arg->getValue(), SymbolMatchStyle, 907 ErrorCallback)) 908 return std::move(E); 909 for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol)) 910 if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create( 911 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 912 return std::move(E); 913 for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbols)) 914 if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc, 915 Arg->getValue(), SymbolMatchStyle, 916 ErrorCallback)) 917 return std::move(E); 918 for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol)) 919 if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create( 920 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 921 return std::move(E); 922 for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbols)) 923 if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc, 924 Arg->getValue(), SymbolMatchStyle, 925 ErrorCallback)) 926 return std::move(E); 927 for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol)) 928 if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( 929 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 930 return std::move(E); 931 for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbols)) 932 if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc, 933 Arg->getValue(), SymbolMatchStyle, 934 ErrorCallback)) 935 return std::move(E); 936 for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol)) 937 if (Error E = 938 Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create( 939 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 940 return std::move(E); 941 for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols)) 942 if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc, 943 Arg->getValue(), SymbolMatchStyle, 944 ErrorCallback)) 945 return std::move(E); 946 for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol)) 947 if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create( 948 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 949 return std::move(E); 950 for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbols)) 951 if (Error E = 952 addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(), 953 SymbolMatchStyle, ErrorCallback)) 954 return std::move(E); 955 for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) { 956 Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue()); 957 if (!SymInfo) 958 return SymInfo.takeError(); 959 960 Config.SymbolsToAdd.push_back(*SymInfo); 961 } 962 963 ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links); 964 965 Config.DeterministicArchives = InputArgs.hasFlag( 966 OBJCOPY_enable_deterministic_archives, 967 OBJCOPY_disable_deterministic_archives, /*default=*/true); 968 969 Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates); 970 971 if (Config.PreserveDates && 972 (Config.OutputFilename == "-" || Config.InputFilename == "-")) 973 return createStringError(errc::invalid_argument, 974 "--preserve-dates requires a file"); 975 976 for (auto Arg : InputArgs) 977 if (Arg->getOption().matches(OBJCOPY_set_start)) { 978 auto EAddr = getAsInteger<uint64_t>(Arg->getValue()); 979 if (!EAddr) 980 return createStringError( 981 EAddr.getError(), "bad entry point address: '%s'", Arg->getValue()); 982 983 ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; }; 984 } else if (Arg->getOption().matches(OBJCOPY_change_start)) { 985 auto EIncr = getAsInteger<int64_t>(Arg->getValue()); 986 if (!EIncr) 987 return createStringError(EIncr.getError(), 988 "bad entry point increment: '%s'", 989 Arg->getValue()); 990 auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr) 991 : [](uint64_t A) { return A; }; 992 ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) { 993 return Expr(EAddr) + *EIncr; 994 }; 995 } 996 997 if (Config.DecompressDebugSections && 998 Config.CompressionType != DebugCompressionType::None) { 999 return createStringError( 1000 errc::invalid_argument, 1001 "cannot specify both --compress-debug-sections and " 1002 "--decompress-debug-sections"); 1003 } 1004 1005 if (Config.DecompressDebugSections && !compression::zlib::isAvailable()) 1006 return createStringError( 1007 errc::invalid_argument, 1008 "LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress"); 1009 1010 if (Config.ExtractPartition && Config.ExtractMainPartition) 1011 return createStringError(errc::invalid_argument, 1012 "cannot specify --extract-partition together with " 1013 "--extract-main-partition"); 1014 1015 DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1016 return std::move(DC); 1017 } 1018 1019 // parseInstallNameToolOptions returns the config and sets the input arguments. 1020 // If a help flag is set then parseInstallNameToolOptions will print the help 1021 // messege and exit. 1022 Expected<DriverConfig> 1023 objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) { 1024 DriverConfig DC; 1025 ConfigManager ConfigMgr; 1026 CommonConfig &Config = ConfigMgr.Common; 1027 MachOConfig &MachOConfig = ConfigMgr.MachO; 1028 InstallNameToolOptTable T; 1029 unsigned MissingArgumentIndex, MissingArgumentCount; 1030 llvm::opt::InputArgList InputArgs = 1031 T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1032 1033 if (MissingArgumentCount) 1034 return createStringError( 1035 errc::invalid_argument, 1036 "missing argument to " + 1037 StringRef(InputArgs.getArgString(MissingArgumentIndex)) + 1038 " option"); 1039 1040 if (InputArgs.size() == 0) { 1041 printHelp(T, errs(), ToolType::InstallNameTool); 1042 exit(1); 1043 } 1044 1045 if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) { 1046 printHelp(T, outs(), ToolType::InstallNameTool); 1047 exit(0); 1048 } 1049 1050 if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) { 1051 outs() << "llvm-install-name-tool, compatible with cctools " 1052 "install_name_tool\n"; 1053 cl::PrintVersionMessage(); 1054 exit(0); 1055 } 1056 1057 for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath)) 1058 MachOConfig.RPathToAdd.push_back(Arg->getValue()); 1059 1060 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath)) 1061 MachOConfig.RPathToPrepend.push_back(Arg->getValue()); 1062 1063 for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) { 1064 StringRef RPath = Arg->getValue(); 1065 1066 // Cannot add and delete the same rpath at the same time. 1067 if (is_contained(MachOConfig.RPathToAdd, RPath)) 1068 return createStringError( 1069 errc::invalid_argument, 1070 "cannot specify both -add_rpath '%s' and -delete_rpath '%s'", 1071 RPath.str().c_str(), RPath.str().c_str()); 1072 if (is_contained(MachOConfig.RPathToPrepend, RPath)) 1073 return createStringError( 1074 errc::invalid_argument, 1075 "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'", 1076 RPath.str().c_str(), RPath.str().c_str()); 1077 1078 MachOConfig.RPathsToRemove.insert(RPath); 1079 } 1080 1081 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) { 1082 StringRef Old = Arg->getValue(0); 1083 StringRef New = Arg->getValue(1); 1084 1085 auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; }; 1086 1087 // Cannot specify duplicate -rpath entries 1088 auto It1 = find_if( 1089 MachOConfig.RPathsToUpdate, 1090 [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) { 1091 return Match(OldNew.getFirst()) || Match(OldNew.getSecond()); 1092 }); 1093 if (It1 != MachOConfig.RPathsToUpdate.end()) 1094 return createStringError(errc::invalid_argument, 1095 "cannot specify both -rpath '" + 1096 It1->getFirst() + "' '" + It1->getSecond() + 1097 "' and -rpath '" + Old + "' '" + New + "'"); 1098 1099 // Cannot specify the same rpath under both -delete_rpath and -rpath 1100 auto It2 = find_if(MachOConfig.RPathsToRemove, Match); 1101 if (It2 != MachOConfig.RPathsToRemove.end()) 1102 return createStringError(errc::invalid_argument, 1103 "cannot specify both -delete_rpath '" + *It2 + 1104 "' and -rpath '" + Old + "' '" + New + "'"); 1105 1106 // Cannot specify the same rpath under both -add_rpath and -rpath 1107 auto It3 = find_if(MachOConfig.RPathToAdd, Match); 1108 if (It3 != MachOConfig.RPathToAdd.end()) 1109 return createStringError(errc::invalid_argument, 1110 "cannot specify both -add_rpath '" + *It3 + 1111 "' and -rpath '" + Old + "' '" + New + "'"); 1112 1113 // Cannot specify the same rpath under both -prepend_rpath and -rpath. 1114 auto It4 = find_if(MachOConfig.RPathToPrepend, Match); 1115 if (It4 != MachOConfig.RPathToPrepend.end()) 1116 return createStringError(errc::invalid_argument, 1117 "cannot specify both -prepend_rpath '" + *It4 + 1118 "' and -rpath '" + Old + "' '" + New + "'"); 1119 1120 MachOConfig.RPathsToUpdate.insert({Old, New}); 1121 } 1122 1123 if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) { 1124 MachOConfig.SharedLibId = Arg->getValue(); 1125 if (MachOConfig.SharedLibId->empty()) 1126 return createStringError(errc::invalid_argument, 1127 "cannot specify an empty id"); 1128 } 1129 1130 for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change)) 1131 MachOConfig.InstallNamesToUpdate.insert( 1132 {Arg->getValue(0), Arg->getValue(1)}); 1133 1134 MachOConfig.RemoveAllRpaths = 1135 InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths); 1136 1137 SmallVector<StringRef, 2> Positional; 1138 for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN)) 1139 return createStringError(errc::invalid_argument, "unknown argument '%s'", 1140 Arg->getAsString(InputArgs).c_str()); 1141 for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT)) 1142 Positional.push_back(Arg->getValue()); 1143 if (Positional.empty()) 1144 return createStringError(errc::invalid_argument, "no input file specified"); 1145 if (Positional.size() > 1) 1146 return createStringError( 1147 errc::invalid_argument, 1148 "llvm-install-name-tool expects a single input file"); 1149 Config.InputFilename = Positional[0]; 1150 Config.OutputFilename = Positional[0]; 1151 1152 DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1153 return std::move(DC); 1154 } 1155 1156 Expected<DriverConfig> 1157 objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr, 1158 function_ref<Error(Error)> ErrorCallback) { 1159 DriverConfig DC; 1160 ConfigManager ConfigMgr; 1161 CommonConfig &Config = ConfigMgr.Common; 1162 MachOConfig &MachOConfig = ConfigMgr.MachO; 1163 BitcodeStripOptTable T; 1164 unsigned MissingArgumentIndex, MissingArgumentCount; 1165 opt::InputArgList InputArgs = 1166 T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1167 1168 if (InputArgs.size() == 0) { 1169 printHelp(T, errs(), ToolType::BitcodeStrip); 1170 exit(1); 1171 } 1172 1173 if (InputArgs.hasArg(BITCODE_STRIP_help)) { 1174 printHelp(T, outs(), ToolType::BitcodeStrip); 1175 exit(0); 1176 } 1177 1178 if (InputArgs.hasArg(BITCODE_STRIP_version)) { 1179 outs() << "llvm-bitcode-strip, compatible with cctools " 1180 "bitcode_strip\n"; 1181 cl::PrintVersionMessage(); 1182 exit(0); 1183 } 1184 1185 for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN)) 1186 return createStringError(errc::invalid_argument, "unknown argument '%s'", 1187 Arg->getAsString(InputArgs).c_str()); 1188 1189 SmallVector<StringRef, 2> Positional; 1190 for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT)) 1191 Positional.push_back(Arg->getValue()); 1192 if (Positional.size() > 1) 1193 return createStringError(errc::invalid_argument, 1194 "llvm-bitcode-strip expects a single input file"); 1195 assert(!Positional.empty()); 1196 Config.InputFilename = Positional[0]; 1197 1198 if (!InputArgs.hasArg(BITCODE_STRIP_output)) { 1199 return createStringError(errc::invalid_argument, 1200 "-o is a required argument"); 1201 } 1202 Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output); 1203 1204 if (!InputArgs.hasArg(BITCODE_STRIP_remove)) 1205 return createStringError(errc::invalid_argument, "no action specified"); 1206 1207 // We only support -r for now, which removes all bitcode sections and 1208 // the __LLVM segment if it's now empty. 1209 cantFail(Config.ToRemove.addMatcher(NameOrPattern::create( 1210 "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback))); 1211 MachOConfig.EmptySegmentsToRemove.insert("__LLVM"); 1212 1213 DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1214 return std::move(DC); 1215 } 1216 1217 // parseStripOptions returns the config and sets the input arguments. If a 1218 // help flag is set then parseStripOptions will print the help messege and 1219 // exit. 1220 Expected<DriverConfig> 1221 objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr, 1222 function_ref<Error(Error)> ErrorCallback) { 1223 const char *const *DashDash = 1224 std::find_if(RawArgsArr.begin(), RawArgsArr.end(), 1225 [](StringRef Str) { return Str == "--"; }); 1226 ArrayRef<const char *> ArgsArr = makeArrayRef(RawArgsArr.begin(), DashDash); 1227 if (DashDash != RawArgsArr.end()) 1228 DashDash = std::next(DashDash); 1229 1230 StripOptTable T; 1231 unsigned MissingArgumentIndex, MissingArgumentCount; 1232 llvm::opt::InputArgList InputArgs = 1233 T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); 1234 1235 if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) { 1236 printHelp(T, errs(), ToolType::Strip); 1237 exit(1); 1238 } 1239 1240 if (InputArgs.hasArg(STRIP_help)) { 1241 printHelp(T, outs(), ToolType::Strip); 1242 exit(0); 1243 } 1244 1245 if (InputArgs.hasArg(STRIP_version)) { 1246 outs() << "llvm-strip, compatible with GNU strip\n"; 1247 cl::PrintVersionMessage(); 1248 exit(0); 1249 } 1250 1251 SmallVector<StringRef, 2> Positional; 1252 for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN)) 1253 return createStringError(errc::invalid_argument, "unknown argument '%s'", 1254 Arg->getAsString(InputArgs).c_str()); 1255 for (auto Arg : InputArgs.filtered(STRIP_INPUT)) 1256 Positional.push_back(Arg->getValue()); 1257 std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional)); 1258 1259 if (Positional.empty()) 1260 return createStringError(errc::invalid_argument, "no input file specified"); 1261 1262 if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output)) 1263 return createStringError( 1264 errc::invalid_argument, 1265 "multiple input files cannot be used in combination with -o"); 1266 1267 ConfigManager ConfigMgr; 1268 CommonConfig &Config = ConfigMgr.Common; 1269 ELFConfig &ELFConfig = ConfigMgr.ELF; 1270 MachOConfig &MachOConfig = ConfigMgr.MachO; 1271 1272 if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard)) 1273 return createStringError(errc::invalid_argument, 1274 "--regex and --wildcard are incompatible"); 1275 MatchStyle SectionMatchStyle = 1276 InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard; 1277 MatchStyle SymbolMatchStyle 1278 = InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex 1279 : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard 1280 : MatchStyle::Literal; 1281 ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links); 1282 Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug); 1283 1284 if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals)) 1285 Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all) 1286 ? DiscardType::All 1287 : DiscardType::Locals; 1288 Config.StripSections = InputArgs.hasArg(STRIP_strip_sections); 1289 Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded); 1290 if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all)) 1291 Config.StripAll = Arg->getOption().getID() == STRIP_strip_all; 1292 Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu); 1293 MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols); 1294 Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug); 1295 ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols); 1296 MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined); 1297 1298 for (auto Arg : InputArgs.filtered(STRIP_keep_section)) 1299 if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create( 1300 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1301 return std::move(E); 1302 1303 for (auto Arg : InputArgs.filtered(STRIP_remove_section)) 1304 if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create( 1305 Arg->getValue(), SectionMatchStyle, ErrorCallback))) 1306 return std::move(E); 1307 1308 for (auto Arg : InputArgs.filtered(STRIP_strip_symbol)) 1309 if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create( 1310 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1311 return std::move(E); 1312 1313 for (auto Arg : InputArgs.filtered(STRIP_keep_symbol)) 1314 if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create( 1315 Arg->getValue(), SymbolMatchStyle, ErrorCallback))) 1316 return std::move(E); 1317 1318 if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug && 1319 !Config.OnlyKeepDebug && !Config.StripUnneeded && 1320 Config.DiscardMode == DiscardType::None && !Config.StripAllGNU && 1321 Config.SymbolsToRemove.empty()) 1322 Config.StripAll = true; 1323 1324 if (Config.DiscardMode == DiscardType::All) { 1325 Config.StripDebug = true; 1326 ELFConfig.KeepFileSymbols = true; 1327 } 1328 1329 Config.DeterministicArchives = 1330 InputArgs.hasFlag(STRIP_enable_deterministic_archives, 1331 STRIP_disable_deterministic_archives, /*default=*/true); 1332 1333 Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates); 1334 Config.InputFormat = FileFormat::Unspecified; 1335 Config.OutputFormat = FileFormat::Unspecified; 1336 1337 DriverConfig DC; 1338 if (Positional.size() == 1) { 1339 Config.InputFilename = Positional[0]; 1340 Config.OutputFilename = 1341 InputArgs.getLastArgValue(STRIP_output, Positional[0]); 1342 DC.CopyConfigs.push_back(std::move(ConfigMgr)); 1343 } else { 1344 StringMap<unsigned> InputFiles; 1345 for (StringRef Filename : Positional) { 1346 if (InputFiles[Filename]++ == 1) { 1347 if (Filename == "-") 1348 return createStringError( 1349 errc::invalid_argument, 1350 "cannot specify '-' as an input file more than once"); 1351 if (Error E = ErrorCallback(createStringError( 1352 errc::invalid_argument, "'%s' was already specified", 1353 Filename.str().c_str()))) 1354 return std::move(E); 1355 } 1356 Config.InputFilename = Filename; 1357 Config.OutputFilename = Filename; 1358 DC.CopyConfigs.push_back(ConfigMgr); 1359 } 1360 } 1361 1362 if (Config.PreserveDates && (is_contained(Positional, "-") || 1363 InputArgs.getLastArgValue(STRIP_output) == "-")) 1364 return createStringError(errc::invalid_argument, 1365 "--preserve-dates requires a file"); 1366 1367 return std::move(DC); 1368 } 1369