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