1 //===- DriverUtils.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 // This file contains utility functions for the driver. Because there 10 // are so many small functions, we created this separate file to make 11 // Driver.cpp less cluttered. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "Config.h" 16 #include "Driver.h" 17 #include "Symbols.h" 18 #include "lld/Common/ErrorHandler.h" 19 #include "lld/Common/Memory.h" 20 #include "llvm/ADT/Optional.h" 21 #include "llvm/ADT/StringSwitch.h" 22 #include "llvm/BinaryFormat/COFF.h" 23 #include "llvm/Object/COFF.h" 24 #include "llvm/Object/WindowsResource.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/MathExtras.h" 31 #include "llvm/Support/Process.h" 32 #include "llvm/Support/Program.h" 33 #include "llvm/Support/raw_ostream.h" 34 #include "llvm/WindowsManifest/WindowsManifestMerger.h" 35 #include <limits> 36 #include <memory> 37 38 using namespace llvm::COFF; 39 using namespace llvm; 40 using llvm::sys::Process; 41 42 namespace lld { 43 namespace coff { 44 namespace { 45 46 const uint16_t SUBLANG_ENGLISH_US = 0x0409; 47 const uint16_t RT_MANIFEST = 24; 48 49 class Executor { 50 public: 51 explicit Executor(StringRef s) : prog(saver().save(s)) {} 52 void add(StringRef s) { args.push_back(saver().save(s)); } 53 void add(std::string &s) { args.push_back(saver().save(s)); } 54 void add(Twine s) { args.push_back(saver().save(s)); } 55 void add(const char *s) { args.push_back(saver().save(s)); } 56 57 void run() { 58 ErrorOr<std::string> exeOrErr = sys::findProgramByName(prog); 59 if (auto ec = exeOrErr.getError()) 60 fatal("unable to find " + prog + " in PATH: " + ec.message()); 61 StringRef exe = saver().save(*exeOrErr); 62 args.insert(args.begin(), exe); 63 64 if (sys::ExecuteAndWait(args[0], args) != 0) 65 fatal("ExecuteAndWait failed: " + 66 llvm::join(args.begin(), args.end(), " ")); 67 } 68 69 private: 70 StringRef prog; 71 std::vector<StringRef> args; 72 }; 73 74 } // anonymous namespace 75 76 // Parses a string in the form of "<integer>[,<integer>]". 77 void parseNumbers(StringRef arg, uint64_t *addr, uint64_t *size) { 78 StringRef s1, s2; 79 std::tie(s1, s2) = arg.split(','); 80 if (s1.getAsInteger(0, *addr)) 81 fatal("invalid number: " + s1); 82 if (size && !s2.empty() && s2.getAsInteger(0, *size)) 83 fatal("invalid number: " + s2); 84 } 85 86 // Parses a string in the form of "<integer>[.<integer>]". 87 // If second number is not present, Minor is set to 0. 88 void parseVersion(StringRef arg, uint32_t *major, uint32_t *minor) { 89 StringRef s1, s2; 90 std::tie(s1, s2) = arg.split('.'); 91 if (s1.getAsInteger(10, *major)) 92 fatal("invalid number: " + s1); 93 *minor = 0; 94 if (!s2.empty() && s2.getAsInteger(10, *minor)) 95 fatal("invalid number: " + s2); 96 } 97 98 void parseGuard(StringRef fullArg) { 99 SmallVector<StringRef, 1> splitArgs; 100 fullArg.split(splitArgs, ","); 101 for (StringRef arg : splitArgs) { 102 if (arg.equals_insensitive("no")) 103 config->guardCF = GuardCFLevel::Off; 104 else if (arg.equals_insensitive("nolongjmp")) 105 config->guardCF &= ~GuardCFLevel::LongJmp; 106 else if (arg.equals_insensitive("noehcont")) 107 config->guardCF &= ~GuardCFLevel::EHCont; 108 else if (arg.equals_insensitive("cf")) 109 config->guardCF = GuardCFLevel::CF; 110 else if (arg.equals_insensitive("longjmp")) 111 config->guardCF |= GuardCFLevel::CF | GuardCFLevel::LongJmp; 112 else if (arg.equals_insensitive("ehcont")) 113 config->guardCF |= GuardCFLevel::CF | GuardCFLevel::EHCont; 114 else 115 fatal("invalid argument to /guard: " + arg); 116 } 117 } 118 119 // Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]". 120 void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major, 121 uint32_t *minor, bool *gotVersion) { 122 StringRef sysStr, ver; 123 std::tie(sysStr, ver) = arg.split(','); 124 std::string sysStrLower = sysStr.lower(); 125 *sys = StringSwitch<WindowsSubsystem>(sysStrLower) 126 .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) 127 .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI) 128 .Case("default", IMAGE_SUBSYSTEM_UNKNOWN) 129 .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION) 130 .Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) 131 .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM) 132 .Case("efi_runtime_driver", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) 133 .Case("native", IMAGE_SUBSYSTEM_NATIVE) 134 .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI) 135 .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI) 136 .Default(IMAGE_SUBSYSTEM_UNKNOWN); 137 if (*sys == IMAGE_SUBSYSTEM_UNKNOWN && sysStrLower != "default") 138 fatal("unknown subsystem: " + sysStr); 139 if (!ver.empty()) 140 parseVersion(ver, major, minor); 141 if (gotVersion) 142 *gotVersion = !ver.empty(); 143 } 144 145 // Parse a string of the form of "<from>=<to>". 146 // Results are directly written to Config. 147 void parseAlternateName(StringRef s) { 148 StringRef from, to; 149 std::tie(from, to) = s.split('='); 150 if (from.empty() || to.empty()) 151 fatal("/alternatename: invalid argument: " + s); 152 auto it = config->alternateNames.find(from); 153 if (it != config->alternateNames.end() && it->second != to) 154 fatal("/alternatename: conflicts: " + s); 155 config->alternateNames.insert(it, std::make_pair(from, to)); 156 } 157 158 // Parse a string of the form of "<from>=<to>". 159 // Results are directly written to Config. 160 void parseMerge(StringRef s) { 161 StringRef from, to; 162 std::tie(from, to) = s.split('='); 163 if (from.empty() || to.empty()) 164 fatal("/merge: invalid argument: " + s); 165 if (from == ".rsrc" || to == ".rsrc") 166 fatal("/merge: cannot merge '.rsrc' with any section"); 167 if (from == ".reloc" || to == ".reloc") 168 fatal("/merge: cannot merge '.reloc' with any section"); 169 auto pair = config->merge.insert(std::make_pair(from, to)); 170 bool inserted = pair.second; 171 if (!inserted) { 172 StringRef existing = pair.first->second; 173 if (existing != to) 174 warn(s + ": already merged into " + existing); 175 } 176 } 177 178 void parsePDBPageSize(StringRef s) { 179 int v; 180 if (s.getAsInteger(0, v)) { 181 error("/pdbpagesize: invalid argument: " + s); 182 return; 183 } 184 if (v != 4096 && v != 8192 && v != 16384 && v != 32768) { 185 error("/pdbpagesize: invalid argument: " + s); 186 return; 187 } 188 189 config->pdbPageSize = v; 190 } 191 192 static uint32_t parseSectionAttributes(StringRef s) { 193 uint32_t ret = 0; 194 for (char c : s.lower()) { 195 switch (c) { 196 case 'd': 197 ret |= IMAGE_SCN_MEM_DISCARDABLE; 198 break; 199 case 'e': 200 ret |= IMAGE_SCN_MEM_EXECUTE; 201 break; 202 case 'k': 203 ret |= IMAGE_SCN_MEM_NOT_CACHED; 204 break; 205 case 'p': 206 ret |= IMAGE_SCN_MEM_NOT_PAGED; 207 break; 208 case 'r': 209 ret |= IMAGE_SCN_MEM_READ; 210 break; 211 case 's': 212 ret |= IMAGE_SCN_MEM_SHARED; 213 break; 214 case 'w': 215 ret |= IMAGE_SCN_MEM_WRITE; 216 break; 217 default: 218 fatal("/section: invalid argument: " + s); 219 } 220 } 221 return ret; 222 } 223 224 // Parses /section option argument. 225 void parseSection(StringRef s) { 226 StringRef name, attrs; 227 std::tie(name, attrs) = s.split(','); 228 if (name.empty() || attrs.empty()) 229 fatal("/section: invalid argument: " + s); 230 config->section[name] = parseSectionAttributes(attrs); 231 } 232 233 // Parses /aligncomm option argument. 234 void parseAligncomm(StringRef s) { 235 StringRef name, align; 236 std::tie(name, align) = s.split(','); 237 if (name.empty() || align.empty()) { 238 error("/aligncomm: invalid argument: " + s); 239 return; 240 } 241 int v; 242 if (align.getAsInteger(0, v)) { 243 error("/aligncomm: invalid argument: " + s); 244 return; 245 } 246 config->alignComm[std::string(name)] = 247 std::max(config->alignComm[std::string(name)], 1 << v); 248 } 249 250 // Parses /functionpadmin option argument. 251 void parseFunctionPadMin(llvm::opt::Arg *a, llvm::COFF::MachineTypes machine) { 252 StringRef arg = a->getNumValues() ? a->getValue() : ""; 253 if (!arg.empty()) { 254 // Optional padding in bytes is given. 255 if (arg.getAsInteger(0, config->functionPadMin)) 256 error("/functionpadmin: invalid argument: " + arg); 257 return; 258 } 259 // No optional argument given. 260 // Set default padding based on machine, similar to link.exe. 261 // There is no default padding for ARM platforms. 262 if (machine == I386) { 263 config->functionPadMin = 5; 264 } else if (machine == AMD64) { 265 config->functionPadMin = 6; 266 } else { 267 error("/functionpadmin: invalid argument for this machine: " + arg); 268 } 269 } 270 271 // Parses a string in the form of "EMBED[,=<integer>]|NO". 272 // Results are directly written to Config. 273 void parseManifest(StringRef arg) { 274 if (arg.equals_insensitive("no")) { 275 config->manifest = Configuration::No; 276 return; 277 } 278 if (!arg.startswith_insensitive("embed")) 279 fatal("invalid option " + arg); 280 config->manifest = Configuration::Embed; 281 arg = arg.substr(strlen("embed")); 282 if (arg.empty()) 283 return; 284 if (!arg.startswith_insensitive(",id=")) 285 fatal("invalid option " + arg); 286 arg = arg.substr(strlen(",id=")); 287 if (arg.getAsInteger(0, config->manifestID)) 288 fatal("invalid option " + arg); 289 } 290 291 // Parses a string in the form of "level=<string>|uiAccess=<string>|NO". 292 // Results are directly written to Config. 293 void parseManifestUAC(StringRef arg) { 294 if (arg.equals_insensitive("no")) { 295 config->manifestUAC = false; 296 return; 297 } 298 for (;;) { 299 arg = arg.ltrim(); 300 if (arg.empty()) 301 return; 302 if (arg.startswith_insensitive("level=")) { 303 arg = arg.substr(strlen("level=")); 304 std::tie(config->manifestLevel, arg) = arg.split(" "); 305 continue; 306 } 307 if (arg.startswith_insensitive("uiaccess=")) { 308 arg = arg.substr(strlen("uiaccess=")); 309 std::tie(config->manifestUIAccess, arg) = arg.split(" "); 310 continue; 311 } 312 fatal("invalid option " + arg); 313 } 314 } 315 316 // Parses a string in the form of "cd|net[,(cd|net)]*" 317 // Results are directly written to Config. 318 void parseSwaprun(StringRef arg) { 319 do { 320 StringRef swaprun, newArg; 321 std::tie(swaprun, newArg) = arg.split(','); 322 if (swaprun.equals_insensitive("cd")) 323 config->swaprunCD = true; 324 else if (swaprun.equals_insensitive("net")) 325 config->swaprunNet = true; 326 else if (swaprun.empty()) 327 error("/swaprun: missing argument"); 328 else 329 error("/swaprun: invalid argument: " + swaprun); 330 // To catch trailing commas, e.g. `/spawrun:cd,` 331 if (newArg.empty() && arg.endswith(",")) 332 error("/swaprun: missing argument"); 333 arg = newArg; 334 } while (!arg.empty()); 335 } 336 337 // An RAII temporary file class that automatically removes a temporary file. 338 namespace { 339 class TemporaryFile { 340 public: 341 TemporaryFile(StringRef prefix, StringRef extn, StringRef contents = "") { 342 SmallString<128> s; 343 if (auto ec = sys::fs::createTemporaryFile("lld-" + prefix, extn, s)) 344 fatal("cannot create a temporary file: " + ec.message()); 345 path = std::string(s.str()); 346 347 if (!contents.empty()) { 348 std::error_code ec; 349 raw_fd_ostream os(path, ec, sys::fs::OF_None); 350 if (ec) 351 fatal("failed to open " + path + ": " + ec.message()); 352 os << contents; 353 } 354 } 355 356 TemporaryFile(TemporaryFile &&obj) { 357 std::swap(path, obj.path); 358 } 359 360 ~TemporaryFile() { 361 if (path.empty()) 362 return; 363 if (sys::fs::remove(path)) 364 fatal("failed to remove " + path); 365 } 366 367 // Returns a memory buffer of this temporary file. 368 // Note that this function does not leave the file open, 369 // so it is safe to remove the file immediately after this function 370 // is called (you cannot remove an opened file on Windows.) 371 std::unique_ptr<MemoryBuffer> getMemoryBuffer() { 372 // IsVolatile=true forces MemoryBuffer to not use mmap(). 373 return CHECK(MemoryBuffer::getFile(path, /*IsText=*/false, 374 /*RequiresNullTerminator=*/false, 375 /*IsVolatile=*/true), 376 "could not open " + path); 377 } 378 379 std::string path; 380 }; 381 } 382 383 static std::string createDefaultXml() { 384 std::string ret; 385 raw_string_ostream os(ret); 386 387 // Emit the XML. Note that we do *not* verify that the XML attributes are 388 // syntactically correct. This is intentional for link.exe compatibility. 389 os << "<?xml version=\"1.0\" standalone=\"yes\"?>\n" 390 << "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n" 391 << " manifestVersion=\"1.0\">\n"; 392 if (config->manifestUAC) { 393 os << " <trustInfo>\n" 394 << " <security>\n" 395 << " <requestedPrivileges>\n" 396 << " <requestedExecutionLevel level=" << config->manifestLevel 397 << " uiAccess=" << config->manifestUIAccess << "/>\n" 398 << " </requestedPrivileges>\n" 399 << " </security>\n" 400 << " </trustInfo>\n"; 401 } 402 for (auto manifestDependency : config->manifestDependencies) { 403 os << " <dependency>\n" 404 << " <dependentAssembly>\n" 405 << " <assemblyIdentity " << manifestDependency << " />\n" 406 << " </dependentAssembly>\n" 407 << " </dependency>\n"; 408 } 409 os << "</assembly>\n"; 410 return os.str(); 411 } 412 413 static std::string createManifestXmlWithInternalMt(StringRef defaultXml) { 414 std::unique_ptr<MemoryBuffer> defaultXmlCopy = 415 MemoryBuffer::getMemBufferCopy(defaultXml); 416 417 windows_manifest::WindowsManifestMerger merger; 418 if (auto e = merger.merge(*defaultXmlCopy.get())) 419 fatal("internal manifest tool failed on default xml: " + 420 toString(std::move(e))); 421 422 for (StringRef filename : config->manifestInput) { 423 std::unique_ptr<MemoryBuffer> manifest = 424 check(MemoryBuffer::getFile(filename)); 425 // Call takeBuffer to include in /reproduce: output if applicable. 426 if (auto e = merger.merge(driver->takeBuffer(std::move(manifest)))) 427 fatal("internal manifest tool failed on file " + filename + ": " + 428 toString(std::move(e))); 429 } 430 431 return std::string(merger.getMergedManifest().get()->getBuffer()); 432 } 433 434 static std::string createManifestXmlWithExternalMt(StringRef defaultXml) { 435 // Create the default manifest file as a temporary file. 436 TemporaryFile Default("defaultxml", "manifest"); 437 std::error_code ec; 438 raw_fd_ostream os(Default.path, ec, sys::fs::OF_TextWithCRLF); 439 if (ec) 440 fatal("failed to open " + Default.path + ": " + ec.message()); 441 os << defaultXml; 442 os.close(); 443 444 // Merge user-supplied manifests if they are given. Since libxml2 is not 445 // enabled, we must shell out to Microsoft's mt.exe tool. 446 TemporaryFile user("user", "manifest"); 447 448 Executor e("mt.exe"); 449 e.add("/manifest"); 450 e.add(Default.path); 451 for (StringRef filename : config->manifestInput) { 452 e.add("/manifest"); 453 e.add(filename); 454 455 // Manually add the file to the /reproduce: tar if needed. 456 if (driver->tar) 457 if (auto mbOrErr = MemoryBuffer::getFile(filename)) 458 driver->takeBuffer(std::move(*mbOrErr)); 459 } 460 e.add("/nologo"); 461 e.add("/out:" + StringRef(user.path)); 462 e.run(); 463 464 return std::string( 465 CHECK(MemoryBuffer::getFile(user.path), "could not open " + user.path) 466 .get() 467 ->getBuffer()); 468 } 469 470 static std::string createManifestXml() { 471 std::string defaultXml = createDefaultXml(); 472 if (config->manifestInput.empty()) 473 return defaultXml; 474 475 if (windows_manifest::isAvailable()) 476 return createManifestXmlWithInternalMt(defaultXml); 477 478 return createManifestXmlWithExternalMt(defaultXml); 479 } 480 481 static std::unique_ptr<WritableMemoryBuffer> 482 createMemoryBufferForManifestRes(size_t manifestSize) { 483 size_t resSize = alignTo( 484 object::WIN_RES_MAGIC_SIZE + object::WIN_RES_NULL_ENTRY_SIZE + 485 sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) + 486 sizeof(object::WinResHeaderSuffix) + manifestSize, 487 object::WIN_RES_DATA_ALIGNMENT); 488 return WritableMemoryBuffer::getNewMemBuffer(resSize, config->outputFile + 489 ".manifest.res"); 490 } 491 492 static void writeResFileHeader(char *&buf) { 493 memcpy(buf, COFF::WinResMagic, sizeof(COFF::WinResMagic)); 494 buf += sizeof(COFF::WinResMagic); 495 memset(buf, 0, object::WIN_RES_NULL_ENTRY_SIZE); 496 buf += object::WIN_RES_NULL_ENTRY_SIZE; 497 } 498 499 static void writeResEntryHeader(char *&buf, size_t manifestSize) { 500 // Write the prefix. 501 auto *prefix = reinterpret_cast<object::WinResHeaderPrefix *>(buf); 502 prefix->DataSize = manifestSize; 503 prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) + 504 sizeof(object::WinResIDs) + 505 sizeof(object::WinResHeaderSuffix); 506 buf += sizeof(object::WinResHeaderPrefix); 507 508 // Write the Type/Name IDs. 509 auto *iDs = reinterpret_cast<object::WinResIDs *>(buf); 510 iDs->setType(RT_MANIFEST); 511 iDs->setName(config->manifestID); 512 buf += sizeof(object::WinResIDs); 513 514 // Write the suffix. 515 auto *suffix = reinterpret_cast<object::WinResHeaderSuffix *>(buf); 516 suffix->DataVersion = 0; 517 suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE; 518 suffix->Language = SUBLANG_ENGLISH_US; 519 suffix->Version = 0; 520 suffix->Characteristics = 0; 521 buf += sizeof(object::WinResHeaderSuffix); 522 } 523 524 // Create a resource file containing a manifest XML. 525 std::unique_ptr<MemoryBuffer> createManifestRes() { 526 std::string manifest = createManifestXml(); 527 528 std::unique_ptr<WritableMemoryBuffer> res = 529 createMemoryBufferForManifestRes(manifest.size()); 530 531 char *buf = res->getBufferStart(); 532 writeResFileHeader(buf); 533 writeResEntryHeader(buf, manifest.size()); 534 535 // Copy the manifest data into the .res file. 536 std::copy(manifest.begin(), manifest.end(), buf); 537 return std::move(res); 538 } 539 540 void createSideBySideManifest() { 541 std::string path = std::string(config->manifestFile); 542 if (path == "") 543 path = config->outputFile + ".manifest"; 544 std::error_code ec; 545 raw_fd_ostream out(path, ec, sys::fs::OF_TextWithCRLF); 546 if (ec) 547 fatal("failed to create manifest: " + ec.message()); 548 out << createManifestXml(); 549 } 550 551 // Parse a string in the form of 552 // "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]" 553 // or "<name>=<dllname>.<name>". 554 // Used for parsing /export arguments. 555 Export parseExport(StringRef arg) { 556 Export e; 557 StringRef rest; 558 std::tie(e.name, rest) = arg.split(","); 559 if (e.name.empty()) 560 goto err; 561 562 if (e.name.contains('=')) { 563 StringRef x, y; 564 std::tie(x, y) = e.name.split("="); 565 566 // If "<name>=<dllname>.<name>". 567 if (y.contains(".")) { 568 e.name = x; 569 e.forwardTo = y; 570 return e; 571 } 572 573 e.extName = x; 574 e.name = y; 575 if (e.name.empty()) 576 goto err; 577 } 578 579 // If "<name>=<internalname>[,@ordinal[,NONAME]][,DATA][,PRIVATE]" 580 while (!rest.empty()) { 581 StringRef tok; 582 std::tie(tok, rest) = rest.split(","); 583 if (tok.equals_insensitive("noname")) { 584 if (e.ordinal == 0) 585 goto err; 586 e.noname = true; 587 continue; 588 } 589 if (tok.equals_insensitive("data")) { 590 e.data = true; 591 continue; 592 } 593 if (tok.equals_insensitive("constant")) { 594 e.constant = true; 595 continue; 596 } 597 if (tok.equals_insensitive("private")) { 598 e.isPrivate = true; 599 continue; 600 } 601 if (tok.startswith("@")) { 602 int32_t ord; 603 if (tok.substr(1).getAsInteger(0, ord)) 604 goto err; 605 if (ord <= 0 || 65535 < ord) 606 goto err; 607 e.ordinal = ord; 608 continue; 609 } 610 goto err; 611 } 612 return e; 613 614 err: 615 fatal("invalid /export: " + arg); 616 } 617 618 static StringRef undecorate(StringRef sym) { 619 if (config->machine != I386) 620 return sym; 621 // In MSVC mode, a fully decorated stdcall function is exported 622 // as-is with the leading underscore (with type IMPORT_NAME). 623 // In MinGW mode, a decorated stdcall function gets the underscore 624 // removed, just like normal cdecl functions. 625 if (sym.startswith("_") && sym.contains('@') && !config->mingw) 626 return sym; 627 return sym.startswith("_") ? sym.substr(1) : sym; 628 } 629 630 // Convert stdcall/fastcall style symbols into unsuffixed symbols, 631 // with or without a leading underscore. (MinGW specific.) 632 static StringRef killAt(StringRef sym, bool prefix) { 633 if (sym.empty()) 634 return sym; 635 // Strip any trailing stdcall suffix 636 sym = sym.substr(0, sym.find('@', 1)); 637 if (!sym.startswith("@")) { 638 if (prefix && !sym.startswith("_")) 639 return saver().save("_" + sym); 640 return sym; 641 } 642 // For fastcall, remove the leading @ and replace it with an 643 // underscore, if prefixes are used. 644 sym = sym.substr(1); 645 if (prefix) 646 sym = saver().save("_" + sym); 647 return sym; 648 } 649 650 // Performs error checking on all /export arguments. 651 // It also sets ordinals. 652 void fixupExports() { 653 // Symbol ordinals must be unique. 654 std::set<uint16_t> ords; 655 for (Export &e : config->exports) { 656 if (e.ordinal == 0) 657 continue; 658 if (!ords.insert(e.ordinal).second) 659 fatal("duplicate export ordinal: " + e.name); 660 } 661 662 for (Export &e : config->exports) { 663 if (!e.forwardTo.empty()) { 664 e.exportName = undecorate(e.name); 665 } else { 666 e.exportName = undecorate(e.extName.empty() ? e.name : e.extName); 667 } 668 } 669 670 if (config->killAt && config->machine == I386) { 671 for (Export &e : config->exports) { 672 e.name = killAt(e.name, true); 673 e.exportName = killAt(e.exportName, false); 674 e.extName = killAt(e.extName, true); 675 e.symbolName = killAt(e.symbolName, true); 676 } 677 } 678 679 // Uniquefy by name. 680 DenseMap<StringRef, Export *> map(config->exports.size()); 681 std::vector<Export> v; 682 for (Export &e : config->exports) { 683 auto pair = map.insert(std::make_pair(e.exportName, &e)); 684 bool inserted = pair.second; 685 if (inserted) { 686 v.push_back(e); 687 continue; 688 } 689 Export *existing = pair.first->second; 690 if (e == *existing || e.name != existing->name) 691 continue; 692 warn("duplicate /export option: " + e.name); 693 } 694 config->exports = std::move(v); 695 696 // Sort by name. 697 std::sort(config->exports.begin(), config->exports.end(), 698 [](const Export &a, const Export &b) { 699 return a.exportName < b.exportName; 700 }); 701 } 702 703 void assignExportOrdinals() { 704 // Assign unique ordinals if default (= 0). 705 uint32_t max = 0; 706 for (Export &e : config->exports) 707 max = std::max(max, (uint32_t)e.ordinal); 708 for (Export &e : config->exports) 709 if (e.ordinal == 0) 710 e.ordinal = ++max; 711 if (max > std::numeric_limits<uint16_t>::max()) 712 fatal("too many exported symbols (max " + 713 Twine(std::numeric_limits<uint16_t>::max()) + ")"); 714 } 715 716 // Parses a string in the form of "key=value" and check 717 // if value matches previous values for the same key. 718 void checkFailIfMismatch(StringRef arg, InputFile *source) { 719 StringRef k, v; 720 std::tie(k, v) = arg.split('='); 721 if (k.empty() || v.empty()) 722 fatal("/failifmismatch: invalid argument: " + arg); 723 std::pair<StringRef, InputFile *> existing = config->mustMatch[k]; 724 if (!existing.first.empty() && v != existing.first) { 725 std::string sourceStr = source ? toString(source) : "cmd-line"; 726 std::string existingStr = 727 existing.second ? toString(existing.second) : "cmd-line"; 728 fatal("/failifmismatch: mismatch detected for '" + k + "':\n>>> " + 729 existingStr + " has value " + existing.first + "\n>>> " + sourceStr + 730 " has value " + v); 731 } 732 config->mustMatch[k] = {v, source}; 733 } 734 735 // Convert Windows resource files (.res files) to a .obj file. 736 // Does what cvtres.exe does, but in-process and cross-platform. 737 MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> mbs, 738 ArrayRef<ObjFile *> objs) { 739 object::WindowsResourceParser parser(/* MinGW */ config->mingw); 740 741 std::vector<std::string> duplicates; 742 for (MemoryBufferRef mb : mbs) { 743 std::unique_ptr<object::Binary> bin = check(object::createBinary(mb)); 744 object::WindowsResource *rf = dyn_cast<object::WindowsResource>(bin.get()); 745 if (!rf) 746 fatal("cannot compile non-resource file as resource"); 747 748 if (auto ec = parser.parse(rf, duplicates)) 749 fatal(toString(std::move(ec))); 750 } 751 752 // Note: This processes all .res files before all objs. Ideally they'd be 753 // handled in the same order they were linked (to keep the right one, if 754 // there are duplicates that are tolerated due to forceMultipleRes). 755 for (ObjFile *f : objs) { 756 object::ResourceSectionRef rsf; 757 if (auto ec = rsf.load(f->getCOFFObj())) 758 fatal(toString(f) + ": " + toString(std::move(ec))); 759 760 if (auto ec = parser.parse(rsf, f->getName(), duplicates)) 761 fatal(toString(std::move(ec))); 762 } 763 764 if (config->mingw) 765 parser.cleanUpManifests(duplicates); 766 767 for (const auto &dupeDiag : duplicates) 768 if (config->forceMultipleRes) 769 warn(dupeDiag); 770 else 771 error(dupeDiag); 772 773 Expected<std::unique_ptr<MemoryBuffer>> e = 774 llvm::object::writeWindowsResourceCOFF(config->machine, parser, 775 config->timestamp); 776 if (!e) 777 fatal("failed to write .res to COFF: " + toString(e.takeError())); 778 779 MemoryBufferRef mbref = **e; 780 make<std::unique_ptr<MemoryBuffer>>(std::move(*e)); // take ownership 781 return mbref; 782 } 783 784 // Create OptTable 785 786 // Create prefix string literals used in Options.td 787 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 788 #include "Options.inc" 789 #undef PREFIX 790 791 // Create table mapping all options defined in Options.td 792 static const llvm::opt::OptTable::Info infoTable[] = { 793 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 794 {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \ 795 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 796 #include "Options.inc" 797 #undef OPTION 798 }; 799 800 COFFOptTable::COFFOptTable() : OptTable(infoTable, true) {} 801 802 COFFOptTable optTable; 803 804 // Set color diagnostics according to --color-diagnostics={auto,always,never} 805 // or --no-color-diagnostics flags. 806 static void handleColorDiagnostics(opt::InputArgList &args) { 807 auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, 808 OPT_no_color_diagnostics); 809 if (!arg) 810 return; 811 if (arg->getOption().getID() == OPT_color_diagnostics) { 812 lld::errs().enable_colors(true); 813 } else if (arg->getOption().getID() == OPT_no_color_diagnostics) { 814 lld::errs().enable_colors(false); 815 } else { 816 StringRef s = arg->getValue(); 817 if (s == "always") 818 lld::errs().enable_colors(true); 819 else if (s == "never") 820 lld::errs().enable_colors(false); 821 else if (s != "auto") 822 error("unknown option: --color-diagnostics=" + s); 823 } 824 } 825 826 static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) { 827 if (auto *arg = args.getLastArg(OPT_rsp_quoting)) { 828 StringRef s = arg->getValue(); 829 if (s != "windows" && s != "posix") 830 error("invalid response file quoting: " + s); 831 if (s == "windows") 832 return cl::TokenizeWindowsCommandLine; 833 return cl::TokenizeGNUCommandLine; 834 } 835 // The COFF linker always defaults to Windows quoting. 836 return cl::TokenizeWindowsCommandLine; 837 } 838 839 // Parses a given list of options. 840 opt::InputArgList ArgParser::parse(ArrayRef<const char *> argv) { 841 // Make InputArgList from string vectors. 842 unsigned missingIndex; 843 unsigned missingCount; 844 845 // We need to get the quoting style for response files before parsing all 846 // options so we parse here before and ignore all the options but 847 // --rsp-quoting and /lldignoreenv. 848 // (This means --rsp-quoting can't be added through %LINK%.) 849 opt::InputArgList args = optTable.ParseArgs(argv, missingIndex, missingCount); 850 851 // Expand response files (arguments in the form of @<filename>) and insert 852 // flags from %LINK% and %_LINK_%, and then parse the argument again. 853 SmallVector<const char *, 256> expandedArgv(argv.data(), 854 argv.data() + argv.size()); 855 if (!args.hasArg(OPT_lldignoreenv)) 856 addLINK(expandedArgv); 857 cl::ExpandResponseFiles(saver(), getQuotingStyle(args), expandedArgv); 858 args = optTable.ParseArgs(makeArrayRef(expandedArgv).drop_front(), 859 missingIndex, missingCount); 860 861 // Print the real command line if response files are expanded. 862 if (args.hasArg(OPT_verbose) && argv.size() != expandedArgv.size()) { 863 std::string msg = "Command line:"; 864 for (const char *s : expandedArgv) 865 msg += " " + std::string(s); 866 message(msg); 867 } 868 869 // Save the command line after response file expansion so we can write it to 870 // the PDB if necessary. 871 config->argv = {expandedArgv.begin(), expandedArgv.end()}; 872 873 // Handle /WX early since it converts missing argument warnings to errors. 874 errorHandler().fatalWarnings = args.hasFlag(OPT_WX, OPT_WX_no, false); 875 876 if (missingCount) 877 fatal(Twine(args.getArgString(missingIndex)) + ": missing argument"); 878 879 handleColorDiagnostics(args); 880 881 for (opt::Arg *arg : args.filtered(OPT_UNKNOWN)) { 882 std::string nearest; 883 if (optTable.findNearest(arg->getAsString(args), nearest) > 1) 884 warn("ignoring unknown argument '" + arg->getAsString(args) + "'"); 885 else 886 warn("ignoring unknown argument '" + arg->getAsString(args) + 887 "', did you mean '" + nearest + "'"); 888 } 889 890 if (args.hasArg(OPT_lib)) 891 warn("ignoring /lib since it's not the first argument"); 892 893 return args; 894 } 895 896 // Tokenizes and parses a given string as command line in .drective section. 897 ParsedDirectives ArgParser::parseDirectives(StringRef s) { 898 ParsedDirectives result; 899 SmallVector<const char *, 16> rest; 900 901 // Handle /EXPORT and /INCLUDE in a fast path. These directives can appear for 902 // potentially every symbol in the object, so they must be handled quickly. 903 SmallVector<StringRef, 16> tokens; 904 cl::TokenizeWindowsCommandLineNoCopy(s, saver(), tokens); 905 for (StringRef tok : tokens) { 906 if (tok.startswith_insensitive("/export:") || 907 tok.startswith_insensitive("-export:")) 908 result.exports.push_back(tok.substr(strlen("/export:"))); 909 else if (tok.startswith_insensitive("/include:") || 910 tok.startswith_insensitive("-include:")) 911 result.includes.push_back(tok.substr(strlen("/include:"))); 912 else { 913 // Copy substrings that are not valid C strings. The tokenizer may have 914 // already copied quoted arguments for us, so those do not need to be 915 // copied again. 916 bool HasNul = tok.end() != s.end() && tok.data()[tok.size()] == '\0'; 917 rest.push_back(HasNul ? tok.data() : saver().save(tok).data()); 918 } 919 } 920 921 // Make InputArgList from unparsed string vectors. 922 unsigned missingIndex; 923 unsigned missingCount; 924 925 result.args = optTable.ParseArgs(rest, missingIndex, missingCount); 926 927 if (missingCount) 928 fatal(Twine(result.args.getArgString(missingIndex)) + ": missing argument"); 929 for (auto *arg : result.args.filtered(OPT_UNKNOWN)) 930 warn("ignoring unknown argument: " + arg->getAsString(result.args)); 931 return result; 932 } 933 934 // link.exe has an interesting feature. If LINK or _LINK_ environment 935 // variables exist, their contents are handled as command line strings. 936 // So you can pass extra arguments using them. 937 void ArgParser::addLINK(SmallVector<const char *, 256> &argv) { 938 // Concatenate LINK env and command line arguments, and then parse them. 939 if (Optional<std::string> s = Process::GetEnv("LINK")) { 940 std::vector<const char *> v = tokenize(*s); 941 argv.insert(std::next(argv.begin()), v.begin(), v.end()); 942 } 943 if (Optional<std::string> s = Process::GetEnv("_LINK_")) { 944 std::vector<const char *> v = tokenize(*s); 945 argv.insert(std::next(argv.begin()), v.begin(), v.end()); 946 } 947 } 948 949 std::vector<const char *> ArgParser::tokenize(StringRef s) { 950 SmallVector<const char *, 16> tokens; 951 cl::TokenizeWindowsCommandLine(s, saver(), tokens); 952 return std::vector<const char *>(tokens.begin(), tokens.end()); 953 } 954 955 void printHelp(const char *argv0) { 956 optTable.printHelp(lld::outs(), 957 (std::string(argv0) + " [options] file...").c_str(), 958 "LLVM Linker", false); 959 } 960 961 } // namespace coff 962 } // namespace lld 963