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 // or "<name>=<dllname>.<name>". 326 // Used for parsing /export arguments. 327 Export parseExport(StringRef Arg) { 328 Export E; 329 StringRef Rest; 330 std::tie(E.Name, Rest) = Arg.split(","); 331 if (E.Name.empty()) 332 goto err; 333 334 if (E.Name.find('=') != StringRef::npos) { 335 StringRef X, Y; 336 std::tie(X, Y) = E.Name.split("="); 337 338 // If "<name>=<dllname>.<name>". 339 if (Y.find(".") != StringRef::npos) { 340 E.Name = X; 341 E.ForwardTo = Y; 342 return E; 343 } 344 345 E.ExtName = X; 346 E.Name = Y; 347 if (E.Name.empty()) 348 goto err; 349 } 350 351 // If "<name>=<internalname>[,@ordinal[,NONAME]][,DATA][,PRIVATE]" 352 while (!Rest.empty()) { 353 StringRef Tok; 354 std::tie(Tok, Rest) = Rest.split(","); 355 if (Tok.equals_lower("noname")) { 356 if (E.Ordinal == 0) 357 goto err; 358 E.Noname = true; 359 continue; 360 } 361 if (Tok.equals_lower("data")) { 362 E.Data = true; 363 continue; 364 } 365 if (Tok.equals_lower("private")) { 366 E.Private = true; 367 continue; 368 } 369 if (Tok.startswith("@")) { 370 int32_t Ord; 371 if (Tok.substr(1).getAsInteger(0, Ord)) 372 goto err; 373 if (Ord <= 0 || 65535 < Ord) 374 goto err; 375 E.Ordinal = Ord; 376 continue; 377 } 378 goto err; 379 } 380 return E; 381 382 err: 383 error(Twine("invalid /export: ") + Arg); 384 } 385 386 static StringRef undecorate(StringRef Sym) { 387 if (Config->Machine != I386) 388 return Sym; 389 return Sym.startswith("_") ? Sym.substr(1) : Sym; 390 } 391 392 // Performs error checking on all /export arguments. 393 // It also sets ordinals. 394 void fixupExports() { 395 // Symbol ordinals must be unique. 396 std::set<uint16_t> Ords; 397 for (Export &E : Config->Exports) { 398 if (E.Ordinal == 0) 399 continue; 400 if (!Ords.insert(E.Ordinal).second) 401 error("duplicate export ordinal: " + E.Name); 402 } 403 404 for (Export &E : Config->Exports) { 405 if (!E.ForwardTo.empty()) { 406 E.SymbolName = E.Name; 407 } else if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) { 408 E.SymbolName = U->getName(); 409 } else { 410 E.SymbolName = E.Sym->getName(); 411 } 412 } 413 414 for (Export &E : Config->Exports) { 415 if (!E.ForwardTo.empty()) { 416 E.ExportName = undecorate(E.Name); 417 } else { 418 E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName); 419 } 420 } 421 422 // Uniquefy by name. 423 std::map<StringRef, Export *> Map; 424 std::vector<Export> V; 425 for (Export &E : Config->Exports) { 426 auto Pair = Map.insert(std::make_pair(E.ExportName, &E)); 427 bool Inserted = Pair.second; 428 if (Inserted) { 429 V.push_back(E); 430 continue; 431 } 432 Export *Existing = Pair.first->second; 433 if (E == *Existing || E.Name != Existing->Name) 434 continue; 435 llvm::errs() << "warning: duplicate /export option: " << E.Name << "\n"; 436 } 437 Config->Exports = std::move(V); 438 439 // Sort by name. 440 std::sort(Config->Exports.begin(), Config->Exports.end(), 441 [](const Export &A, const Export &B) { 442 return A.ExportName < B.ExportName; 443 }); 444 } 445 446 void assignExportOrdinals() { 447 // Assign unique ordinals if default (= 0). 448 uint16_t Max = 0; 449 for (Export &E : Config->Exports) 450 Max = std::max(Max, E.Ordinal); 451 for (Export &E : Config->Exports) 452 if (E.Ordinal == 0) 453 E.Ordinal = ++Max; 454 } 455 456 // Parses a string in the form of "key=value" and check 457 // if value matches previous values for the same key. 458 void checkFailIfMismatch(StringRef Arg) { 459 StringRef K, V; 460 std::tie(K, V) = Arg.split('='); 461 if (K.empty() || V.empty()) 462 error(Twine("/failifmismatch: invalid argument: ") + Arg); 463 StringRef Existing = Config->MustMatch[K]; 464 if (!Existing.empty() && V != Existing) 465 error(Twine("/failifmismatch: mismatch detected: ") + Existing + " and " + 466 V + " for key " + K); 467 Config->MustMatch[K] = V; 468 } 469 470 // Convert Windows resource files (.res files) to a .obj file 471 // using cvtres.exe. 472 std::unique_ptr<MemoryBuffer> 473 convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) { 474 // Create an output file path. 475 SmallString<128> Path; 476 if (llvm::sys::fs::createTemporaryFile("resource", "obj", Path)) 477 error("Could not create temporary file"); 478 479 // Execute cvtres.exe. 480 Executor E("cvtres.exe"); 481 E.add("/machine:" + machineToStr(Config->Machine)); 482 E.add("/readonly"); 483 E.add("/nologo"); 484 E.add("/out:" + Path); 485 for (MemoryBufferRef MB : MBs) 486 E.add(MB.getBufferIdentifier()); 487 E.run(); 488 ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(Path); 489 error(Ret, Twine("Could not open ") + Path); 490 return std::move(*Ret); 491 } 492 493 static std::string writeToTempFile(StringRef Contents) { 494 SmallString<128> Path; 495 int FD; 496 if (llvm::sys::fs::createTemporaryFile("tmp", "def", FD, Path)) { 497 llvm::errs() << "failed to create a temporary file\n"; 498 return ""; 499 } 500 llvm::raw_fd_ostream OS(FD, /*shouldClose*/ true); 501 OS << Contents; 502 return Path.str(); 503 } 504 505 void touchFile(StringRef Path) { 506 int FD; 507 std::error_code EC = sys::fs::openFileForWrite(Path, FD, sys::fs::F_Append); 508 error(EC, "failed to create a file"); 509 sys::Process::SafelyCloseFileDescriptor(FD); 510 } 511 512 static std::string getImplibPath() { 513 if (!Config->Implib.empty()) 514 return Config->Implib; 515 SmallString<128> Out = StringRef(Config->OutputFile); 516 sys::path::replace_extension(Out, ".lib"); 517 return Out.str(); 518 } 519 520 static std::unique_ptr<MemoryBuffer> createEmptyImportLibrary() { 521 std::string S = (Twine("LIBRARY \"") + 522 llvm::sys::path::filename(Config->OutputFile) + "\"\n") 523 .str(); 524 std::string Path1 = writeToTempFile(S); 525 std::string Path2 = getImplibPath(); 526 llvm::FileRemover Remover1(Path1); 527 llvm::FileRemover Remover2(Path2); 528 529 Executor E("lib.exe"); 530 E.add("/nologo"); 531 E.add("/machine:" + machineToStr(Config->Machine)); 532 E.add(Twine("/def:") + Path1); 533 E.add(Twine("/out:") + Path2); 534 E.run(); 535 536 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 537 MemoryBuffer::getFile(Path2, -1, false); 538 error(BufOrErr, Twine("Failed to open ") + Path2); 539 return MemoryBuffer::getMemBufferCopy((*BufOrErr)->getBuffer()); 540 } 541 542 static std::vector<NewArchiveIterator> 543 readMembers(const object::Archive &Archive) { 544 std::vector<NewArchiveIterator> V; 545 for (const auto &ChildOrErr : Archive.children()) { 546 error(ChildOrErr, "Archive::Child::getName failed"); 547 const object::Archive::Child C(*ChildOrErr); 548 ErrorOr<StringRef> NameOrErr = C.getName(); 549 error(NameOrErr, "Archive::Child::getName failed"); 550 V.emplace_back(C, *NameOrErr); 551 } 552 return V; 553 } 554 555 // This class creates short import files which is described in 556 // PE/COFF spec 7. Import Library Format. 557 class ShortImportCreator { 558 public: 559 ShortImportCreator(object::Archive *A, StringRef S) : Parent(A), DLLName(S) {} 560 561 NewArchiveIterator create(StringRef Sym, uint16_t Ordinal, 562 ImportNameType NameType, bool isData) { 563 size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs 564 size_t Size = sizeof(object::ArchiveMemberHeader) + 565 sizeof(coff_import_header) + ImpSize; 566 char *Buf = Alloc.Allocate<char>(Size); 567 memset(Buf, 0, Size); 568 char *P = Buf; 569 570 // Write archive member header 571 auto *Hdr = reinterpret_cast<object::ArchiveMemberHeader *>(P); 572 P += sizeof(*Hdr); 573 sprintf(Hdr->Name, "%-12s", "dummy"); 574 sprintf(Hdr->LastModified, "%-12d", 0); 575 sprintf(Hdr->UID, "%-6d", 0); 576 sprintf(Hdr->GID, "%-6d", 0); 577 sprintf(Hdr->AccessMode, "%-8d", 0644); 578 sprintf(Hdr->Size, "%-10d", int(sizeof(coff_import_header) + ImpSize)); 579 580 // Write short import library. 581 auto *Imp = reinterpret_cast<coff_import_header *>(P); 582 P += sizeof(*Imp); 583 Imp->Sig2 = 0xFFFF; 584 Imp->Machine = Config->Machine; 585 Imp->SizeOfData = ImpSize; 586 if (Ordinal > 0) 587 Imp->OrdinalHint = Ordinal; 588 Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE); 589 Imp->TypeInfo |= NameType << 2; 590 591 // Write symbol name and DLL name. 592 memcpy(P, Sym.data(), Sym.size()); 593 P += Sym.size() + 1; 594 memcpy(P, DLLName.data(), DLLName.size()); 595 596 std::error_code EC; 597 object::Archive::Child C(Parent, Buf, &EC); 598 assert(!EC && "We created an invalid buffer"); 599 return NewArchiveIterator(C, DLLName); 600 } 601 602 private: 603 BumpPtrAllocator Alloc; 604 object::Archive *Parent; 605 StringRef DLLName; 606 }; 607 608 static ImportNameType getNameType(StringRef Sym, StringRef ExtName) { 609 if (Sym != ExtName) 610 return IMPORT_NAME_UNDECORATE; 611 if (Config->Machine == I386 && Sym.startswith("_")) 612 return IMPORT_NAME_NOPREFIX; 613 return IMPORT_NAME; 614 } 615 616 static std::string replace(StringRef S, StringRef From, StringRef To) { 617 size_t Pos = S.find(From); 618 assert(Pos != StringRef::npos); 619 return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str(); 620 } 621 622 // Creates an import library for a DLL. In this function, we first 623 // create an empty import library using lib.exe and then adds short 624 // import files to that file. 625 void writeImportLibrary() { 626 std::unique_ptr<MemoryBuffer> Buf = createEmptyImportLibrary(); 627 std::error_code EC; 628 object::Archive Archive(Buf->getMemBufferRef(), EC); 629 error(EC, "Error reading an empty import file"); 630 std::vector<NewArchiveIterator> Members = readMembers(Archive); 631 632 std::string DLLName = llvm::sys::path::filename(Config->OutputFile); 633 ShortImportCreator ShortImport(&Archive, DLLName); 634 for (Export &E : Config->Exports) { 635 if (E.Private) 636 continue; 637 if (E.ExtName.empty()) { 638 Members.push_back(ShortImport.create( 639 E.SymbolName, E.Ordinal, getNameType(E.SymbolName, E.Name), E.Data)); 640 } else { 641 Members.push_back(ShortImport.create( 642 replace(E.SymbolName, E.Name, E.ExtName), E.Ordinal, 643 getNameType(E.SymbolName, E.Name), E.Data)); 644 } 645 } 646 647 std::string Path = getImplibPath(); 648 std::pair<StringRef, std::error_code> Result = 649 writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU, 650 /*Deterministic*/ true, /*Thin*/ false); 651 error(Result.second, Twine("Failed to write ") + Path); 652 } 653 654 // Create OptTable 655 656 // Create prefix string literals used in Options.td 657 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 658 #include "Options.inc" 659 #undef PREFIX 660 661 // Create table mapping all options defined in Options.td 662 static const llvm::opt::OptTable::Info infoTable[] = { 663 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ 664 { \ 665 X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ 666 OPT_##GROUP, OPT_##ALIAS, X6 \ 667 }, 668 #include "Options.inc" 669 #undef OPTION 670 }; 671 672 class COFFOptTable : public llvm::opt::OptTable { 673 public: 674 COFFOptTable() : OptTable(infoTable, true) {} 675 }; 676 677 // Parses a given list of options. 678 llvm::opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) { 679 // First, replace respnose files (@<file>-style options). 680 std::vector<const char *> Argv = replaceResponseFiles(ArgsArr); 681 682 // Make InputArgList from string vectors. 683 COFFOptTable Table; 684 unsigned MissingIndex; 685 unsigned MissingCount; 686 llvm::opt::InputArgList Args = 687 Table.ParseArgs(Argv, MissingIndex, MissingCount); 688 689 // Print the real command line if response files are expanded. 690 if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) { 691 llvm::outs() << "Command line:"; 692 for (const char *S : Argv) 693 llvm::outs() << " " << S; 694 llvm::outs() << "\n"; 695 } 696 697 if (MissingCount) 698 error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) + 699 "\", expected " + Twine(MissingCount) + 700 (MissingCount == 1 ? " argument." : " arguments.")); 701 for (auto *Arg : Args.filtered(OPT_UNKNOWN)) 702 llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n"; 703 return Args; 704 } 705 706 llvm::opt::InputArgList ArgParser::parseLINK(ArrayRef<const char *> Args) { 707 // Concatenate LINK env and given arguments and parse them. 708 Optional<std::string> Env = Process::GetEnv("LINK"); 709 if (!Env) 710 return parse(Args); 711 std::vector<const char *> V = tokenize(*Env); 712 V.insert(V.end(), Args.begin(), Args.end()); 713 return parse(V); 714 } 715 716 std::vector<const char *> ArgParser::tokenize(StringRef S) { 717 SmallVector<const char *, 16> Tokens; 718 StringSaver Saver(AllocAux); 719 llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens); 720 return std::vector<const char *>(Tokens.begin(), Tokens.end()); 721 } 722 723 // Creates a new command line by replacing options starting with '@' 724 // character. '@<filename>' is replaced by the file's contents. 725 std::vector<const char *> 726 ArgParser::replaceResponseFiles(std::vector<const char *> Argv) { 727 SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size()); 728 StringSaver Saver(AllocAux); 729 ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens); 730 return std::vector<const char *>(Tokens.begin(), Tokens.end()); 731 } 732 733 void printHelp(const char *Argv0) { 734 COFFOptTable Table; 735 Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false); 736 } 737 738 } // namespace coff 739 } // namespace lld 740