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