1 //===- DriverUtils.cpp ----------------------------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains utility functions for the driver. Because there 11 // are so many small functions, we created this separate file to make 12 // Driver.cpp less cluttered. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "Config.h" 17 #include "Driver.h" 18 #include "Error.h" 19 #include "Symbols.h" 20 #include "llvm/ADT/Optional.h" 21 #include "llvm/ADT/StringSwitch.h" 22 #include "llvm/Object/Archive.h" 23 #include "llvm/Object/ArchiveWriter.h" 24 #include "llvm/Object/COFF.h" 25 #include "llvm/Option/Arg.h" 26 #include "llvm/Option/ArgList.h" 27 #include "llvm/Option/Option.h" 28 #include "llvm/Support/CommandLine.h" 29 #include "llvm/Support/FileUtilities.h" 30 #include "llvm/Support/Path.h" 31 #include "llvm/Support/Process.h" 32 #include "llvm/Support/Program.h" 33 #include "llvm/Support/raw_ostream.h" 34 #include <memory> 35 36 using namespace llvm::COFF; 37 using namespace llvm; 38 using llvm::cl::ExpandResponseFiles; 39 using llvm::cl::TokenizeWindowsCommandLine; 40 using llvm::sys::Process; 41 42 namespace lld { 43 namespace coff { 44 namespace { 45 46 class Executor { 47 public: 48 explicit Executor(StringRef S) : Saver(Alloc), Prog(Saver.save(S)) {} 49 void add(StringRef S) { Args.push_back(Saver.save(S)); } 50 void add(std::string &S) { Args.push_back(Saver.save(S)); } 51 void add(Twine S) { Args.push_back(Saver.save(S)); } 52 void add(const char *S) { Args.push_back(Saver.save(S)); } 53 54 void run() { 55 ErrorOr<std::string> ExeOrErr = llvm::sys::findProgramByName(Prog); 56 error(ExeOrErr, Twine("unable to find ") + Prog + " in PATH: "); 57 const char *Exe = Saver.save(*ExeOrErr); 58 Args.insert(Args.begin(), Exe); 59 Args.push_back(nullptr); 60 if (llvm::sys::ExecuteAndWait(Args[0], Args.data()) != 0) { 61 for (const char *S : Args) 62 if (S) 63 llvm::errs() << S << " "; 64 error("failed"); 65 } 66 } 67 68 private: 69 llvm::BumpPtrAllocator Alloc; 70 llvm::StringSaver Saver; 71 StringRef Prog; 72 std::vector<const char *> Args; 73 }; 74 75 } // anonymous namespace 76 77 // Returns /machine's value. 78 MachineTypes getMachineType(StringRef S) { 79 MachineTypes MT = StringSwitch<MachineTypes>(S.lower()) 80 .Case("x64", AMD64) 81 .Case("amd64", AMD64) 82 .Case("x86", I386) 83 .Case("i386", I386) 84 .Case("arm", ARMNT) 85 .Default(IMAGE_FILE_MACHINE_UNKNOWN); 86 if (MT != IMAGE_FILE_MACHINE_UNKNOWN) 87 return MT; 88 error(Twine("unknown /machine argument: ") + S); 89 } 90 91 StringRef machineToStr(MachineTypes MT) { 92 switch (MT) { 93 case ARMNT: 94 return "arm"; 95 case AMD64: 96 return "x64"; 97 case I386: 98 return "x86"; 99 default: 100 llvm_unreachable("unknown machine type"); 101 } 102 } 103 104 // Parses a string in the form of "<integer>[,<integer>]". 105 void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) { 106 StringRef S1, S2; 107 std::tie(S1, S2) = Arg.split(','); 108 if (S1.getAsInteger(0, *Addr)) 109 error(Twine("invalid number: ") + S1); 110 if (Size && !S2.empty() && S2.getAsInteger(0, *Size)) 111 error(Twine("invalid number: ") + S2); 112 } 113 114 // Parses a string in the form of "<integer>[.<integer>]". 115 // If second number is not present, Minor is set to 0. 116 void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) { 117 StringRef S1, S2; 118 std::tie(S1, S2) = Arg.split('.'); 119 if (S1.getAsInteger(0, *Major)) 120 error(Twine("invalid number: ") + S1); 121 *Minor = 0; 122 if (!S2.empty() && S2.getAsInteger(0, *Minor)) 123 error(Twine("invalid number: ") + S2); 124 } 125 126 // Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]". 127 void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major, 128 uint32_t *Minor) { 129 StringRef SysStr, Ver; 130 std::tie(SysStr, Ver) = Arg.split(','); 131 *Sys = StringSwitch<WindowsSubsystem>(SysStr.lower()) 132 .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) 133 .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI) 134 .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION) 135 .Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) 136 .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM) 137 .Case("efi_runtime_driver", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) 138 .Case("native", IMAGE_SUBSYSTEM_NATIVE) 139 .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI) 140 .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI) 141 .Default(IMAGE_SUBSYSTEM_UNKNOWN); 142 if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN) 143 error(Twine("unknown subsystem: ") + SysStr); 144 if (!Ver.empty()) 145 parseVersion(Ver, Major, Minor); 146 } 147 148 // Parse a string of the form of "<from>=<to>". 149 // Results are directly written to Config. 150 void parseAlternateName(StringRef S) { 151 StringRef From, To; 152 std::tie(From, To) = S.split('='); 153 if (From.empty() || To.empty()) 154 error(Twine("/alternatename: invalid argument: ") + S); 155 auto It = Config->AlternateNames.find(From); 156 if (It != Config->AlternateNames.end() && It->second != To) 157 error(Twine("/alternatename: conflicts: ") + S); 158 Config->AlternateNames.insert(It, std::make_pair(From, To)); 159 } 160 161 // Parse a string of the form of "<from>=<to>". 162 // Results are directly written to Config. 163 void parseMerge(StringRef S) { 164 StringRef From, To; 165 std::tie(From, To) = S.split('='); 166 if (From.empty() || To.empty()) 167 error(Twine("/merge: invalid argument: ") + S); 168 auto Pair = Config->Merge.insert(std::make_pair(From, To)); 169 bool Inserted = Pair.second; 170 if (!Inserted) { 171 StringRef Existing = Pair.first->second; 172 if (Existing != To) 173 llvm::errs() << "warning: " << S << ": already merged into " 174 << Existing << "\n"; 175 } 176 } 177 178 // Parses a string in the form of "EMBED[,=<integer>]|NO". 179 // Results are directly written to Config. 180 void parseManifest(StringRef Arg) { 181 if (Arg.equals_lower("no")) { 182 Config->Manifest = Configuration::No; 183 return; 184 } 185 if (!Arg.startswith_lower("embed")) 186 error(Twine("Invalid option ") + Arg); 187 Config->Manifest = Configuration::Embed; 188 Arg = Arg.substr(strlen("embed")); 189 if (Arg.empty()) 190 return; 191 if (!Arg.startswith_lower(",id=")) 192 error(Twine("Invalid option ") + Arg); 193 Arg = Arg.substr(strlen(",id=")); 194 if (Arg.getAsInteger(0, Config->ManifestID)) 195 error(Twine("Invalid option ") + Arg); 196 } 197 198 // Parses a string in the form of "level=<string>|uiAccess=<string>|NO". 199 // Results are directly written to Config. 200 void parseManifestUAC(StringRef Arg) { 201 if (Arg.equals_lower("no")) { 202 Config->ManifestUAC = false; 203 return; 204 } 205 for (;;) { 206 Arg = Arg.ltrim(); 207 if (Arg.empty()) 208 return; 209 if (Arg.startswith_lower("level=")) { 210 Arg = Arg.substr(strlen("level=")); 211 std::tie(Config->ManifestLevel, Arg) = Arg.split(" "); 212 continue; 213 } 214 if (Arg.startswith_lower("uiaccess=")) { 215 Arg = Arg.substr(strlen("uiaccess=")); 216 std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" "); 217 continue; 218 } 219 error(Twine("Invalid option ") + Arg); 220 } 221 } 222 223 // Quote each line with "". Existing double-quote is converted 224 // to two double-quotes. 225 static void quoteAndPrint(raw_ostream &Out, StringRef S) { 226 while (!S.empty()) { 227 StringRef Line; 228 std::tie(Line, S) = S.split("\n"); 229 if (Line.empty()) 230 continue; 231 Out << '\"'; 232 for (int I = 0, E = Line.size(); I != E; ++I) { 233 if (Line[I] == '\"') { 234 Out << "\"\""; 235 } else { 236 Out << Line[I]; 237 } 238 } 239 Out << "\"\n"; 240 } 241 } 242 243 // Create a manifest file contents. 244 static std::string createManifestXml() { 245 std::string S; 246 llvm::raw_string_ostream OS(S); 247 // Emit the XML. Note that we do *not* verify that the XML attributes are 248 // syntactically correct. This is intentional for link.exe compatibility. 249 OS << "<?xml version=\"1.0\" standalone=\"yes\"?>\n" 250 << "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n" 251 << " manifestVersion=\"1.0\">\n"; 252 if (Config->ManifestUAC) { 253 OS << " <trustInfo>\n" 254 << " <security>\n" 255 << " <requestedPrivileges>\n" 256 << " <requestedExecutionLevel level=" << Config->ManifestLevel 257 << " uiAccess=" << Config->ManifestUIAccess << "/>\n" 258 << " </requestedPrivileges>\n" 259 << " </security>\n" 260 << " </trustInfo>\n"; 261 if (!Config->ManifestDependency.empty()) { 262 OS << " <dependency>\n" 263 << " <dependentAssembly>\n" 264 << " <assemblyIdentity " << Config->ManifestDependency << " />\n" 265 << " </dependentAssembly>\n" 266 << " </dependency>\n"; 267 } 268 } 269 OS << "</assembly>\n"; 270 OS.flush(); 271 return S; 272 } 273 274 // Create a resource file containing a manifest XML. 275 std::unique_ptr<MemoryBuffer> createManifestRes() { 276 // Create a temporary file for the resource script file. 277 SmallString<128> RCPath; 278 std::error_code EC = sys::fs::createTemporaryFile("tmp", "rc", RCPath); 279 error(EC, "cannot create a temporary file"); 280 FileRemover RCRemover(RCPath); 281 282 // Open the temporary file for writing. 283 llvm::raw_fd_ostream Out(RCPath, EC, sys::fs::F_Text); 284 error(EC, Twine("failed to open ") + RCPath); 285 286 // Write resource script to the RC file. 287 Out << "#define LANG_ENGLISH 9\n" 288 << "#define SUBLANG_DEFAULT 1\n" 289 << "#define APP_MANIFEST " << Config->ManifestID << "\n" 290 << "#define RT_MANIFEST 24\n" 291 << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n" 292 << "APP_MANIFEST RT_MANIFEST {\n"; 293 quoteAndPrint(Out, createManifestXml()); 294 Out << "}\n"; 295 Out.close(); 296 297 // Create output resource file. 298 SmallString<128> ResPath; 299 EC = sys::fs::createTemporaryFile("tmp", "res", ResPath); 300 error(EC, "cannot create a temporary file"); 301 302 Executor E("rc.exe"); 303 E.add("/fo"); 304 E.add(ResPath.str()); 305 E.add("/nologo"); 306 E.add(RCPath.str()); 307 E.run(); 308 ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(ResPath); 309 error(Ret, Twine("Could not open ") + ResPath); 310 return std::move(*Ret); 311 } 312 313 void createSideBySideManifest() { 314 std::string Path = Config->ManifestFile; 315 if (Path == "") 316 Path = (Twine(Config->OutputFile) + ".manifest").str(); 317 std::error_code EC; 318 llvm::raw_fd_ostream Out(Path, EC, llvm::sys::fs::F_Text); 319 error(EC, "failed to create manifest"); 320 Out << createManifestXml(); 321 } 322 323 // Parse a string in the form of 324 // "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]". 325 // Used for parsing /export arguments. 326 Export parseExport(StringRef Arg) { 327 Export E; 328 StringRef Rest; 329 std::tie(E.Name, Rest) = Arg.split(","); 330 if (E.Name.empty()) 331 goto err; 332 if (E.Name.find('=') != StringRef::npos) { 333 std::tie(E.ExtName, E.Name) = E.Name.split("="); 334 if (E.Name.empty()) 335 goto err; 336 } 337 338 while (!Rest.empty()) { 339 StringRef Tok; 340 std::tie(Tok, Rest) = Rest.split(","); 341 if (Tok.equals_lower("noname")) { 342 if (E.Ordinal == 0) 343 goto err; 344 E.Noname = true; 345 continue; 346 } 347 if (Tok.equals_lower("data")) { 348 E.Data = true; 349 continue; 350 } 351 if (Tok.equals_lower("private")) { 352 E.Private = true; 353 continue; 354 } 355 if (Tok.startswith("@")) { 356 int32_t Ord; 357 if (Tok.substr(1).getAsInteger(0, Ord)) 358 goto err; 359 if (Ord <= 0 || 65535 < Ord) 360 goto err; 361 E.Ordinal = Ord; 362 continue; 363 } 364 goto err; 365 } 366 return E; 367 368 err: 369 error(Twine("invalid /export: ") + Arg); 370 } 371 372 static StringRef undecorate(StringRef Sym) { 373 if (Config->Machine != I386) 374 return Sym; 375 return Sym.startswith("_") ? Sym.substr(1) : Sym; 376 } 377 378 // Performs error checking on all /export arguments. 379 // It also sets ordinals. 380 void fixupExports() { 381 // Symbol ordinals must be unique. 382 std::set<uint16_t> Ords; 383 for (Export &E : Config->Exports) { 384 if (E.Ordinal == 0) 385 continue; 386 if (!Ords.insert(E.Ordinal).second) 387 error("duplicate export ordinal: " + E.Name); 388 } 389 390 for (Export &E : Config->Exports) { 391 if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) { 392 E.SymbolName = U->getName(); 393 } else { 394 E.SymbolName = E.Sym->getName(); 395 } 396 } 397 398 for (Export &E : Config->Exports) 399 E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName); 400 401 // Uniquefy by name. 402 std::map<StringRef, Export *> Map; 403 std::vector<Export> V; 404 for (Export &E : Config->Exports) { 405 auto Pair = Map.insert(std::make_pair(E.ExportName, &E)); 406 bool Inserted = Pair.second; 407 if (Inserted) { 408 V.push_back(E); 409 continue; 410 } 411 Export *Existing = Pair.first->second; 412 if (E == *Existing || E.Name != Existing->Name) 413 continue; 414 llvm::errs() << "warning: duplicate /export option: " << E.Name << "\n"; 415 } 416 Config->Exports = std::move(V); 417 418 // Sort by name. 419 std::sort(Config->Exports.begin(), Config->Exports.end(), 420 [](const Export &A, const Export &B) { 421 return A.ExportName < B.ExportName; 422 }); 423 } 424 425 void assignExportOrdinals() { 426 // Assign unique ordinals if default (= 0). 427 uint16_t Max = 0; 428 for (Export &E : Config->Exports) 429 Max = std::max(Max, E.Ordinal); 430 for (Export &E : Config->Exports) 431 if (E.Ordinal == 0) 432 E.Ordinal = ++Max; 433 } 434 435 // Parses a string in the form of "key=value" and check 436 // if value matches previous values for the same key. 437 void checkFailIfMismatch(StringRef Arg) { 438 StringRef K, V; 439 std::tie(K, V) = Arg.split('='); 440 if (K.empty() || V.empty()) 441 error(Twine("/failifmismatch: invalid argument: ") + Arg); 442 StringRef Existing = Config->MustMatch[K]; 443 if (!Existing.empty() && V != Existing) 444 error(Twine("/failifmismatch: mismatch detected: ") + Existing + " and " + 445 V + " for key " + K); 446 Config->MustMatch[K] = V; 447 } 448 449 // Convert Windows resource files (.res files) to a .obj file 450 // using cvtres.exe. 451 std::unique_ptr<MemoryBuffer> 452 convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) { 453 // Create an output file path. 454 SmallString<128> Path; 455 if (llvm::sys::fs::createTemporaryFile("resource", "obj", Path)) 456 error("Could not create temporary file"); 457 458 // Execute cvtres.exe. 459 Executor E("cvtres.exe"); 460 E.add("/machine:" + machineToStr(Config->Machine)); 461 E.add("/readonly"); 462 E.add("/nologo"); 463 E.add("/out:" + Path); 464 for (MemoryBufferRef MB : MBs) 465 E.add(MB.getBufferIdentifier()); 466 E.run(); 467 ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(Path); 468 error(Ret, Twine("Could not open ") + Path); 469 return std::move(*Ret); 470 } 471 472 static std::string writeToTempFile(StringRef Contents) { 473 SmallString<128> Path; 474 int FD; 475 if (llvm::sys::fs::createTemporaryFile("tmp", "def", FD, Path)) { 476 llvm::errs() << "failed to create a temporary file\n"; 477 return ""; 478 } 479 llvm::raw_fd_ostream OS(FD, /*shouldClose*/ true); 480 OS << Contents; 481 return Path.str(); 482 } 483 484 void touchFile(StringRef Path) { 485 int FD; 486 std::error_code EC = sys::fs::openFileForWrite(Path, FD, sys::fs::F_Append); 487 error(EC, "failed to create a file"); 488 sys::Process::SafelyCloseFileDescriptor(FD); 489 } 490 491 static std::string getImplibPath() { 492 if (!Config->Implib.empty()) 493 return Config->Implib; 494 SmallString<128> Out = StringRef(Config->OutputFile); 495 sys::path::replace_extension(Out, ".lib"); 496 return Out.str(); 497 } 498 499 static std::unique_ptr<MemoryBuffer> createEmptyImportLibrary() { 500 std::string S = (Twine("LIBRARY \"") + 501 llvm::sys::path::filename(Config->OutputFile) + "\"\n") 502 .str(); 503 std::string Path1 = writeToTempFile(S); 504 std::string Path2 = getImplibPath(); 505 llvm::FileRemover Remover1(Path1); 506 llvm::FileRemover Remover2(Path2); 507 508 Executor E("lib.exe"); 509 E.add("/nologo"); 510 E.add("/machine:" + machineToStr(Config->Machine)); 511 E.add(Twine("/def:") + Path1); 512 E.add(Twine("/out:") + Path2); 513 E.run(); 514 515 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 516 MemoryBuffer::getFile(Path2, -1, false); 517 error(BufOrErr, Twine("Failed to open ") + Path2); 518 return MemoryBuffer::getMemBufferCopy((*BufOrErr)->getBuffer()); 519 } 520 521 static std::vector<NewArchiveIterator> 522 readMembers(const object::Archive &Archive) { 523 std::vector<NewArchiveIterator> V; 524 for (const object::Archive::Child &C : Archive.children()) { 525 ErrorOr<StringRef> NameOrErr = C.getName(); 526 error(NameOrErr, "Archive::Child::getName failed"); 527 V.emplace_back(C, *NameOrErr); 528 } 529 return V; 530 } 531 532 // This class creates short import files which is described in 533 // PE/COFF spec 7. Import Library Format. 534 class ShortImportCreator { 535 public: 536 ShortImportCreator(object::Archive *A, StringRef S) : Parent(A), DLLName(S) {} 537 538 NewArchiveIterator create(StringRef Sym, uint16_t Ordinal, 539 ImportNameType NameType, bool isData) { 540 size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs 541 size_t Size = sizeof(object::ArchiveMemberHeader) + 542 sizeof(coff_import_header) + ImpSize; 543 char *Buf = Alloc.Allocate<char>(Size); 544 memset(Buf, 0, Size); 545 char *P = Buf; 546 547 // Write archive member header 548 auto *Hdr = reinterpret_cast<object::ArchiveMemberHeader *>(P); 549 P += sizeof(*Hdr); 550 sprintf(Hdr->Name, "%-12s", "dummy"); 551 sprintf(Hdr->LastModified, "%-12d", 0); 552 sprintf(Hdr->UID, "%-6d", 0); 553 sprintf(Hdr->GID, "%-6d", 0); 554 sprintf(Hdr->AccessMode, "%-8d", 0644); 555 sprintf(Hdr->Size, "%-10d", int(sizeof(coff_import_header) + ImpSize)); 556 557 // Write short import library. 558 auto *Imp = reinterpret_cast<coff_import_header *>(P); 559 P += sizeof(*Imp); 560 Imp->Sig2 = 0xFFFF; 561 Imp->Machine = Config->Machine; 562 Imp->SizeOfData = ImpSize; 563 if (Ordinal > 0) 564 Imp->OrdinalHint = Ordinal; 565 Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE); 566 Imp->TypeInfo |= NameType << 2; 567 568 // Write symbol name and DLL name. 569 memcpy(P, Sym.data(), Sym.size()); 570 P += Sym.size() + 1; 571 memcpy(P, DLLName.data(), DLLName.size()); 572 573 object::Archive::Child C(Parent, Buf); 574 return NewArchiveIterator(C, DLLName); 575 } 576 577 private: 578 BumpPtrAllocator Alloc; 579 object::Archive *Parent; 580 StringRef DLLName; 581 }; 582 583 static ImportNameType getNameType(StringRef Sym, StringRef ExtName) { 584 if (Sym != ExtName) 585 return IMPORT_NAME_UNDECORATE; 586 if (Config->Machine == I386 && Sym.startswith("_")) 587 return IMPORT_NAME_NOPREFIX; 588 return IMPORT_NAME; 589 } 590 591 static std::string replace(StringRef S, StringRef From, StringRef To) { 592 size_t Pos = S.find(From); 593 assert(Pos != StringRef::npos); 594 return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str(); 595 } 596 597 // Creates an import library for a DLL. In this function, we first 598 // create an empty import library using lib.exe and then adds short 599 // import files to that file. 600 void writeImportLibrary() { 601 std::unique_ptr<MemoryBuffer> Buf = createEmptyImportLibrary(); 602 std::error_code EC; 603 object::Archive Archive(Buf->getMemBufferRef(), EC); 604 error(EC, "Error reading an empty import file"); 605 std::vector<NewArchiveIterator> Members = readMembers(Archive); 606 607 std::string DLLName = llvm::sys::path::filename(Config->OutputFile); 608 ShortImportCreator ShortImport(&Archive, DLLName); 609 for (Export &E : Config->Exports) { 610 if (E.Private) 611 continue; 612 if (E.ExtName.empty()) { 613 Members.push_back(ShortImport.create( 614 E.SymbolName, E.Ordinal, getNameType(E.SymbolName, E.Name), E.Data)); 615 } else { 616 Members.push_back(ShortImport.create( 617 replace(E.SymbolName, E.Name, E.ExtName), E.Ordinal, 618 getNameType(E.SymbolName, E.Name), E.Data)); 619 } 620 } 621 622 std::string Path = getImplibPath(); 623 std::pair<StringRef, std::error_code> Result = 624 writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU, 625 /*Deterministic*/ true, /*Thin*/ false); 626 error(Result.second, Twine("Failed to write ") + Path); 627 } 628 629 // Create OptTable 630 631 // Create prefix string literals used in Options.td 632 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 633 #include "Options.inc" 634 #undef PREFIX 635 636 // Create table mapping all options defined in Options.td 637 static const llvm::opt::OptTable::Info infoTable[] = { 638 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ 639 { \ 640 X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ 641 OPT_##GROUP, OPT_##ALIAS, X6 \ 642 }, 643 #include "Options.inc" 644 #undef OPTION 645 }; 646 647 class COFFOptTable : public llvm::opt::OptTable { 648 public: 649 COFFOptTable() : OptTable(infoTable, true) {} 650 }; 651 652 // Parses a given list of options. 653 llvm::opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) { 654 // First, replace respnose files (@<file>-style options). 655 std::vector<const char *> Argv = replaceResponseFiles(ArgsArr); 656 657 // Make InputArgList from string vectors. 658 COFFOptTable Table; 659 unsigned MissingIndex; 660 unsigned MissingCount; 661 llvm::opt::InputArgList Args = 662 Table.ParseArgs(Argv, MissingIndex, MissingCount); 663 664 // Print the real command line if response files are expanded. 665 if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) { 666 llvm::outs() << "Command line:"; 667 for (const char *S : Argv) 668 llvm::outs() << " " << S; 669 llvm::outs() << "\n"; 670 } 671 672 if (MissingCount) 673 error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) + 674 "\", expected " + Twine(MissingCount) + 675 (MissingCount == 1 ? " argument." : " arguments.")); 676 for (auto *Arg : Args.filtered(OPT_UNKNOWN)) 677 llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n"; 678 return Args; 679 } 680 681 llvm::opt::InputArgList ArgParser::parseLINK(ArrayRef<const char *> Args) { 682 // Concatenate LINK env and given arguments and parse them. 683 Optional<std::string> Env = Process::GetEnv("LINK"); 684 if (!Env) 685 return parse(Args); 686 std::vector<const char *> V = tokenize(*Env); 687 V.insert(V.end(), Args.begin(), Args.end()); 688 return parse(V); 689 } 690 691 std::vector<const char *> ArgParser::tokenize(StringRef S) { 692 SmallVector<const char *, 16> Tokens; 693 StringSaver Saver(AllocAux); 694 llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens); 695 return std::vector<const char *>(Tokens.begin(), Tokens.end()); 696 } 697 698 // Creates a new command line by replacing options starting with '@' 699 // character. '@<filename>' is replaced by the file's contents. 700 std::vector<const char *> 701 ArgParser::replaceResponseFiles(std::vector<const char *> Argv) { 702 SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size()); 703 StringSaver Saver(AllocAux); 704 ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens); 705 return std::vector<const char *>(Tokens.begin(), Tokens.end()); 706 } 707 708 void printHelp(const char *Argv0) { 709 COFFOptTable Table; 710 Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false); 711 } 712 713 } // namespace coff 714 } // namespace lld 715