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