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