PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/project/lld/COFF/DriverUtils.cpp

https://gitlab.com/torshie/modern-tool
C++ | 650 lines | 537 code | 50 blank | 63 comment | 105 complexity | b99dd7b43e7ced87ec375cf15d500b8e MD5 | raw file
Possible License(s): BSD-3-Clause, 0BSD, BSD-2-Clause, GPL-2.0, GPL-3.0, LGPL-2.0, Apache-2.0
  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. #include "Config.h"
  16. #include "Driver.h"
  17. #include "Error.h"
  18. #include "llvm/ADT/Optional.h"
  19. #include "llvm/ADT/STLExtras.h"
  20. #include "llvm/ADT/StringSwitch.h"
  21. #include "llvm/Object/COFF.h"
  22. #include "llvm/Option/Arg.h"
  23. #include "llvm/Option/ArgList.h"
  24. #include "llvm/Option/Option.h"
  25. #include "llvm/Support/CommandLine.h"
  26. #include "llvm/Support/FileUtilities.h"
  27. #include "llvm/Support/Path.h"
  28. #include "llvm/Support/Process.h"
  29. #include "llvm/Support/Program.h"
  30. #include "llvm/Support/raw_ostream.h"
  31. #include <memory>
  32. using namespace llvm::COFF;
  33. using namespace llvm;
  34. using llvm::cl::ExpandResponseFiles;
  35. using llvm::cl::TokenizeWindowsCommandLine;
  36. using llvm::sys::Process;
  37. namespace lld {
  38. namespace coff {
  39. namespace {
  40. class Executor {
  41. public:
  42. explicit Executor(StringRef S) : Saver(Alloc), Prog(Saver.save(S)) {}
  43. void add(StringRef S) { Args.push_back(Saver.save(S)); }
  44. void add(std::string &S) { Args.push_back(Saver.save(S)); }
  45. void add(Twine S) { Args.push_back(Saver.save(S)); }
  46. void add(const char *S) { Args.push_back(Saver.save(S)); }
  47. std::error_code run() {
  48. ErrorOr<std::string> ExeOrErr = llvm::sys::findProgramByName(Prog);
  49. if (auto EC = ExeOrErr.getError()) {
  50. llvm::errs() << "unable to find " << Prog << " in PATH: "
  51. << EC.message() << "\n";
  52. return make_error_code(LLDError::InvalidOption);
  53. }
  54. const char *Exe = Saver.save(ExeOrErr.get());
  55. Args.insert(Args.begin(), Exe);
  56. Args.push_back(nullptr);
  57. if (llvm::sys::ExecuteAndWait(Args[0], Args.data()) != 0) {
  58. for (const char *S : Args)
  59. if (S)
  60. llvm::errs() << S << " ";
  61. llvm::errs() << "failed\n";
  62. return make_error_code(LLDError::InvalidOption);
  63. }
  64. return std::error_code();
  65. }
  66. private:
  67. llvm::BumpPtrAllocator Alloc;
  68. llvm::BumpPtrStringSaver Saver;
  69. StringRef Prog;
  70. std::vector<const char *> Args;
  71. };
  72. } // anonymous namespace
  73. // Returns /machine's value.
  74. ErrorOr<MachineTypes> getMachineType(StringRef S) {
  75. MachineTypes MT = StringSwitch<MachineTypes>(S.lower())
  76. .Case("x64", IMAGE_FILE_MACHINE_AMD64)
  77. .Case("amd64", IMAGE_FILE_MACHINE_AMD64)
  78. .Case("x86", IMAGE_FILE_MACHINE_I386)
  79. .Case("i386", IMAGE_FILE_MACHINE_I386)
  80. .Case("arm", IMAGE_FILE_MACHINE_ARMNT)
  81. .Default(IMAGE_FILE_MACHINE_UNKNOWN);
  82. if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
  83. return MT;
  84. llvm::errs() << "unknown /machine argument" << S << "\n";
  85. return make_error_code(LLDError::InvalidOption);
  86. }
  87. StringRef machineTypeToStr(MachineTypes MT) {
  88. switch (MT) {
  89. case IMAGE_FILE_MACHINE_ARMNT:
  90. return "arm";
  91. case IMAGE_FILE_MACHINE_AMD64:
  92. return "x64";
  93. case IMAGE_FILE_MACHINE_I386:
  94. return "x86";
  95. default:
  96. llvm_unreachable("unknown machine type");
  97. }
  98. }
  99. // Parses a string in the form of "<integer>[,<integer>]".
  100. std::error_code parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) {
  101. StringRef S1, S2;
  102. std::tie(S1, S2) = Arg.split(',');
  103. if (S1.getAsInteger(0, *Addr)) {
  104. llvm::errs() << "invalid number: " << S1 << "\n";
  105. return make_error_code(LLDError::InvalidOption);
  106. }
  107. if (Size && !S2.empty() && S2.getAsInteger(0, *Size)) {
  108. llvm::errs() << "invalid number: " << S2 << "\n";
  109. return make_error_code(LLDError::InvalidOption);
  110. }
  111. return std::error_code();
  112. }
  113. // Parses a string in the form of "<integer>[.<integer>]".
  114. // If second number is not present, Minor is set to 0.
  115. std::error_code parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) {
  116. StringRef S1, S2;
  117. std::tie(S1, S2) = Arg.split('.');
  118. if (S1.getAsInteger(0, *Major)) {
  119. llvm::errs() << "invalid number: " << S1 << "\n";
  120. return make_error_code(LLDError::InvalidOption);
  121. }
  122. *Minor = 0;
  123. if (!S2.empty() && S2.getAsInteger(0, *Minor)) {
  124. llvm::errs() << "invalid number: " << S2 << "\n";
  125. return make_error_code(LLDError::InvalidOption);
  126. }
  127. return std::error_code();
  128. }
  129. // Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
  130. std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
  131. uint32_t *Major, uint32_t *Minor) {
  132. StringRef SysStr, Ver;
  133. std::tie(SysStr, Ver) = Arg.split(',');
  134. *Sys = StringSwitch<WindowsSubsystem>(SysStr.lower())
  135. .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
  136. .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI)
  137. .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION)
  138. .Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
  139. .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM)
  140. .Case("efi_runtime_driver", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
  141. .Case("native", IMAGE_SUBSYSTEM_NATIVE)
  142. .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI)
  143. .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI)
  144. .Default(IMAGE_SUBSYSTEM_UNKNOWN);
  145. if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN) {
  146. llvm::errs() << "unknown subsystem: " << SysStr << "\n";
  147. return make_error_code(LLDError::InvalidOption);
  148. }
  149. if (!Ver.empty())
  150. if (auto EC = parseVersion(Ver, Major, Minor))
  151. return EC;
  152. return std::error_code();
  153. }
  154. // Parse a string of the form of "<from>=<to>".
  155. // Results are directly written to Config.
  156. std::error_code parseAlternateName(StringRef S) {
  157. StringRef From, To;
  158. std::tie(From, To) = S.split('=');
  159. if (From.empty() || To.empty()) {
  160. llvm::errs() << "/alternatename: invalid argument: " << S << "\n";
  161. return make_error_code(LLDError::InvalidOption);
  162. }
  163. auto It = Config->AlternateNames.find(From);
  164. if (It != Config->AlternateNames.end() && It->second != To) {
  165. llvm::errs() << "/alternatename: conflicts: " << S << "\n";
  166. return make_error_code(LLDError::InvalidOption);
  167. }
  168. Config->AlternateNames.insert(It, std::make_pair(From, To));
  169. return std::error_code();
  170. }
  171. // Parse a string of the form of "<from>=<to>".
  172. // Results are directly written to Config.
  173. std::error_code parseMerge(StringRef S) {
  174. StringRef From, To;
  175. std::tie(From, To) = S.split('=');
  176. if (From.empty() || To.empty()) {
  177. llvm::errs() << "/merge: invalid argument: " << S << "\n";
  178. return make_error_code(LLDError::InvalidOption);
  179. }
  180. auto Pair = Config->Merge.insert(std::make_pair(From, To));
  181. bool Inserted = Pair.second;
  182. if (!Inserted) {
  183. StringRef Existing = Pair.first->second;
  184. if (Existing != To)
  185. llvm::errs() << "warning: " << S << ": already merged into "
  186. << Existing << "\n";
  187. }
  188. return std::error_code();
  189. }
  190. // Parses a string in the form of "EMBED[,=<integer>]|NO".
  191. // Results are directly written to Config.
  192. std::error_code parseManifest(StringRef Arg) {
  193. if (Arg.equals_lower("no")) {
  194. Config->Manifest = Configuration::No;
  195. return std::error_code();
  196. }
  197. if (!Arg.startswith_lower("embed"))
  198. return make_error_code(LLDError::InvalidOption);
  199. Config->Manifest = Configuration::Embed;
  200. Arg = Arg.substr(strlen("embed"));
  201. if (Arg.empty())
  202. return std::error_code();
  203. if (!Arg.startswith_lower(",id="))
  204. return make_error_code(LLDError::InvalidOption);
  205. Arg = Arg.substr(strlen(",id="));
  206. if (Arg.getAsInteger(0, Config->ManifestID))
  207. return make_error_code(LLDError::InvalidOption);
  208. return std::error_code();
  209. }
  210. // Parses a string in the form of "level=<string>|uiAccess=<string>|NO".
  211. // Results are directly written to Config.
  212. std::error_code parseManifestUAC(StringRef Arg) {
  213. if (Arg.equals_lower("no")) {
  214. Config->ManifestUAC = false;
  215. return std::error_code();
  216. }
  217. for (;;) {
  218. Arg = Arg.ltrim();
  219. if (Arg.empty())
  220. return std::error_code();
  221. if (Arg.startswith_lower("level=")) {
  222. Arg = Arg.substr(strlen("level="));
  223. std::tie(Config->ManifestLevel, Arg) = Arg.split(" ");
  224. continue;
  225. }
  226. if (Arg.startswith_lower("uiaccess=")) {
  227. Arg = Arg.substr(strlen("uiaccess="));
  228. std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" ");
  229. continue;
  230. }
  231. return make_error_code(LLDError::InvalidOption);
  232. }
  233. }
  234. // Quote each line with "". Existing double-quote is converted
  235. // to two double-quotes.
  236. static void quoteAndPrint(raw_ostream &Out, StringRef S) {
  237. while (!S.empty()) {
  238. StringRef Line;
  239. std::tie(Line, S) = S.split("\n");
  240. if (Line.empty())
  241. continue;
  242. Out << '\"';
  243. for (int I = 0, E = Line.size(); I != E; ++I) {
  244. if (Line[I] == '\"') {
  245. Out << "\"\"";
  246. } else {
  247. Out << Line[I];
  248. }
  249. }
  250. Out << "\"\n";
  251. }
  252. }
  253. // Create a manifest file contents.
  254. static std::string createManifestXml() {
  255. std::string S;
  256. llvm::raw_string_ostream OS(S);
  257. // Emit the XML. Note that we do *not* verify that the XML attributes are
  258. // syntactically correct. This is intentional for link.exe compatibility.
  259. OS << "<?xml version=\"1.0\" standalone=\"yes\"?>\n"
  260. << "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n"
  261. << " manifestVersion=\"1.0\">\n";
  262. if (Config->ManifestUAC) {
  263. OS << " <trustInfo>\n"
  264. << " <security>\n"
  265. << " <requestedPrivileges>\n"
  266. << " <requestedExecutionLevel level=" << Config->ManifestLevel
  267. << " uiAccess=" << Config->ManifestUIAccess << "/>\n"
  268. << " </requestedPrivileges>\n"
  269. << " </security>\n"
  270. << " </trustInfo>\n";
  271. if (!Config->ManifestDependency.empty()) {
  272. OS << " <dependency>\n"
  273. << " <dependentAssembly>\n"
  274. << " <assemblyIdentity " << Config->ManifestDependency << " />\n"
  275. << " </dependentAssembly>\n"
  276. << " </dependency>\n";
  277. }
  278. }
  279. OS << "</assembly>\n";
  280. OS.flush();
  281. return S;
  282. }
  283. // Create a resource file containing a manifest XML.
  284. ErrorOr<std::unique_ptr<MemoryBuffer>> createManifestRes() {
  285. // Create a temporary file for the resource script file.
  286. SmallString<128> RCPath;
  287. if (sys::fs::createTemporaryFile("tmp", "rc", RCPath)) {
  288. llvm::errs() << "cannot create a temporary file\n";
  289. return make_error_code(LLDError::InvalidOption);
  290. }
  291. FileRemover RCRemover(RCPath);
  292. // Open the temporary file for writing.
  293. std::error_code EC;
  294. llvm::raw_fd_ostream Out(RCPath, EC, sys::fs::F_Text);
  295. if (EC) {
  296. llvm::errs() << "failed to open " << RCPath << ": " << EC.message() << "\n";
  297. return make_error_code(LLDError::InvalidOption);
  298. }
  299. // Write resource script to the RC file.
  300. Out << "#define LANG_ENGLISH 9\n"
  301. << "#define SUBLANG_DEFAULT 1\n"
  302. << "#define APP_MANIFEST " << Config->ManifestID << "\n"
  303. << "#define RT_MANIFEST 24\n"
  304. << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n"
  305. << "APP_MANIFEST RT_MANIFEST {\n";
  306. quoteAndPrint(Out, createManifestXml());
  307. Out << "}\n";
  308. Out.close();
  309. // Create output resource file.
  310. SmallString<128> ResPath;
  311. if (sys::fs::createTemporaryFile("tmp", "res", ResPath)) {
  312. llvm::errs() << "cannot create a temporary file\n";
  313. return make_error_code(LLDError::InvalidOption);
  314. }
  315. Executor E("rc.exe");
  316. E.add("/fo");
  317. E.add(ResPath.str());
  318. E.add("/nologo");
  319. E.add(RCPath.str());
  320. if (auto EC = E.run())
  321. return EC;
  322. return MemoryBuffer::getFile(ResPath);
  323. }
  324. std::error_code createSideBySideManifest() {
  325. std::string Path = Config->ManifestFile;
  326. if (Path == "")
  327. Path = (Twine(Config->OutputFile) + ".manifest").str();
  328. std::error_code EC;
  329. llvm::raw_fd_ostream Out(Path, EC, llvm::sys::fs::F_Text);
  330. if (EC) {
  331. llvm::errs() << EC.message() << "\n";
  332. return EC;
  333. }
  334. Out << createManifestXml();
  335. return std::error_code();
  336. }
  337. // Parse a string in the form of
  338. // "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]".
  339. // Used for parsing /export arguments.
  340. ErrorOr<Export> parseExport(StringRef Arg) {
  341. Export E;
  342. StringRef Rest;
  343. std::tie(E.Name, Rest) = Arg.split(",");
  344. if (E.Name.empty())
  345. goto err;
  346. if (E.Name.find('=') != StringRef::npos) {
  347. std::tie(E.ExtName, E.Name) = E.Name.split("=");
  348. if (E.Name.empty())
  349. goto err;
  350. } else {
  351. E.ExtName = E.Name;
  352. }
  353. while (!Rest.empty()) {
  354. StringRef Tok;
  355. std::tie(Tok, Rest) = Rest.split(",");
  356. if (Tok.equals_lower("noname")) {
  357. if (E.Ordinal == 0)
  358. goto err;
  359. E.Noname = true;
  360. continue;
  361. }
  362. if (Tok.equals_lower("data")) {
  363. E.Data = true;
  364. continue;
  365. }
  366. if (Tok.equals_lower("private")) {
  367. E.Private = true;
  368. continue;
  369. }
  370. if (Tok.startswith("@")) {
  371. int32_t Ord;
  372. if (Tok.substr(1).getAsInteger(0, Ord))
  373. goto err;
  374. if (Ord <= 0 || 65535 < Ord)
  375. goto err;
  376. E.Ordinal = Ord;
  377. continue;
  378. }
  379. goto err;
  380. }
  381. return E;
  382. err:
  383. llvm::errs() << "invalid /export: " << Arg << "\n";
  384. return make_error_code(LLDError::InvalidOption);
  385. }
  386. // Performs error checking on all /export arguments.
  387. // It also sets ordinals.
  388. std::error_code fixupExports() {
  389. // Symbol ordinals must be unique.
  390. std::set<uint16_t> Ords;
  391. for (Export &E : Config->Exports) {
  392. if (E.Ordinal == 0)
  393. continue;
  394. if (!Ords.insert(E.Ordinal).second) {
  395. llvm::errs() << "duplicate export ordinal: " << E.Name << "\n";
  396. return make_error_code(LLDError::InvalidOption);
  397. }
  398. }
  399. // Uniquefy by name.
  400. std::map<StringRef, Export *> Map;
  401. std::vector<Export> V;
  402. for (Export &E : Config->Exports) {
  403. auto Pair = Map.insert(std::make_pair(E.Name, &E));
  404. bool Inserted = Pair.second;
  405. if (Inserted) {
  406. V.push_back(E);
  407. continue;
  408. }
  409. Export *Existing = Pair.first->second;
  410. if (E == *Existing)
  411. continue;
  412. llvm::errs() << "warning: duplicate /export option: " << E.Name << "\n";
  413. continue;
  414. }
  415. Config->Exports = std::move(V);
  416. // Sort by name.
  417. std::sort(
  418. Config->Exports.begin(), Config->Exports.end(),
  419. [](const Export &A, const Export &B) { return A.ExtName < B.ExtName; });
  420. // Assign unique ordinals if default (= 0).
  421. uint16_t Max = 0;
  422. for (Export &E : Config->Exports)
  423. Max = std::max(Max, E.Ordinal);
  424. for (Export &E : Config->Exports)
  425. if (E.Ordinal == 0)
  426. E.Ordinal = ++Max;
  427. return std::error_code();
  428. }
  429. // Parses a string in the form of "key=value" and check
  430. // if value matches previous values for the same key.
  431. std::error_code checkFailIfMismatch(StringRef Arg) {
  432. StringRef K, V;
  433. std::tie(K, V) = Arg.split('=');
  434. if (K.empty() || V.empty()) {
  435. llvm::errs() << "/failifmismatch: invalid argument: " << Arg << "\n";
  436. return make_error_code(LLDError::InvalidOption);
  437. }
  438. StringRef Existing = Config->MustMatch[K];
  439. if (!Existing.empty() && V != Existing) {
  440. llvm::errs() << "/failifmismatch: mismatch detected: "
  441. << Existing << " and " << V << " for key " << K << "\n";
  442. return make_error_code(LLDError::InvalidOption);
  443. }
  444. Config->MustMatch[K] = V;
  445. return std::error_code();
  446. }
  447. // Convert Windows resource files (.res files) to a .obj file
  448. // using cvtres.exe.
  449. ErrorOr<std::unique_ptr<MemoryBuffer>>
  450. convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
  451. // Create an output file path.
  452. SmallString<128> Path;
  453. if (llvm::sys::fs::createTemporaryFile("resource", "obj", Path))
  454. return make_error_code(LLDError::InvalidOption);
  455. // Execute cvtres.exe.
  456. Executor E("cvtres.exe");
  457. E.add("/machine:" + machineTypeToStr(Config->MachineType));
  458. E.add("/readonly");
  459. E.add("/nologo");
  460. E.add("/out:" + Path);
  461. for (MemoryBufferRef MB : MBs)
  462. E.add(MB.getBufferIdentifier());
  463. if (auto EC = E.run())
  464. return EC;
  465. return MemoryBuffer::getFile(Path);
  466. }
  467. static std::string writeToTempFile(StringRef Contents) {
  468. SmallString<128> Path;
  469. int FD;
  470. if (llvm::sys::fs::createTemporaryFile("tmp", "def", FD, Path)) {
  471. llvm::errs() << "failed to create a temporary file\n";
  472. return "";
  473. }
  474. llvm::raw_fd_ostream OS(FD, /*shouldClose*/ true);
  475. OS << Contents;
  476. return Path.str();
  477. }
  478. /// Creates a .def file containing the list of exported symbols.
  479. static std::string createModuleDefinitionFile() {
  480. std::string S;
  481. llvm::raw_string_ostream OS(S);
  482. OS << "LIBRARY \"" << llvm::sys::path::filename(Config->OutputFile) << "\"\n"
  483. << "EXPORTS\n";
  484. for (Export &E : Config->Exports) {
  485. OS << " " << E.ExtName;
  486. if (E.Ordinal > 0)
  487. OS << " @" << E.Ordinal;
  488. if (E.Noname)
  489. OS << " NONAME";
  490. if (E.Data)
  491. OS << " DATA";
  492. if (E.Private)
  493. OS << " PRIVATE";
  494. OS << "\n";
  495. }
  496. OS.flush();
  497. return S;
  498. }
  499. // Creates a .def file and runs lib.exe on it to create an import library.
  500. std::error_code writeImportLibrary() {
  501. std::string Contents = createModuleDefinitionFile();
  502. std::string Def = writeToTempFile(Contents);
  503. llvm::FileRemover TempFile(Def);
  504. Executor E("lib.exe");
  505. E.add("/nologo");
  506. E.add("/machine:" + machineTypeToStr(Config->MachineType));
  507. E.add(Twine("/def:") + Def);
  508. if (Config->Implib.empty()) {
  509. SmallString<128> Out = StringRef(Config->OutputFile);
  510. sys::path::replace_extension(Out, ".lib");
  511. E.add("/out:" + Out);
  512. } else {
  513. E.add("/out:" + Config->Implib);
  514. }
  515. return E.run();
  516. }
  517. void touchFile(StringRef Path) {
  518. int FD;
  519. if (sys::fs::openFileForWrite(Path, FD, sys::fs::F_Append))
  520. report_fatal_error("failed to create a file");
  521. sys::Process::SafelyCloseFileDescriptor(FD);
  522. }
  523. // Create OptTable
  524. // Create prefix string literals used in Options.td
  525. #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
  526. #include "Options.inc"
  527. #undef PREFIX
  528. // Create table mapping all options defined in Options.td
  529. static const llvm::opt::OptTable::Info infoTable[] = {
  530. #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
  531. { \
  532. X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \
  533. OPT_##GROUP, OPT_##ALIAS, X6 \
  534. },
  535. #include "Options.inc"
  536. #undef OPTION
  537. };
  538. class COFFOptTable : public llvm::opt::OptTable {
  539. public:
  540. COFFOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable), true) {}
  541. };
  542. // Parses a given list of options.
  543. ErrorOr<llvm::opt::InputArgList>
  544. ArgParser::parse(ArrayRef<const char *> ArgsArr) {
  545. // First, replace respnose files (@<file>-style options).
  546. auto ArgvOrErr = replaceResponseFiles(ArgsArr);
  547. if (auto EC = ArgvOrErr.getError()) {
  548. llvm::errs() << "error while reading response file: " << EC.message()
  549. << "\n";
  550. return EC;
  551. }
  552. std::vector<const char *> Argv = std::move(ArgvOrErr.get());
  553. // Make InputArgList from string vectors.
  554. COFFOptTable Table;
  555. unsigned MissingIndex;
  556. unsigned MissingCount;
  557. llvm::opt::InputArgList Args =
  558. Table.ParseArgs(Argv, MissingIndex, MissingCount);
  559. if (MissingCount) {
  560. llvm::errs() << "missing arg value for \""
  561. << Args.getArgString(MissingIndex) << "\", expected "
  562. << MissingCount
  563. << (MissingCount == 1 ? " argument.\n" : " arguments.\n");
  564. return make_error_code(LLDError::InvalidOption);
  565. }
  566. for (auto *Arg : Args.filtered(OPT_UNKNOWN))
  567. llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
  568. return std::move(Args);
  569. }
  570. ErrorOr<llvm::opt::InputArgList>
  571. ArgParser::parseLINK(ArrayRef<const char *> Args) {
  572. // Concatenate LINK env and given arguments and parse them.
  573. Optional<std::string> Env = Process::GetEnv("LINK");
  574. if (!Env)
  575. return parse(Args);
  576. std::vector<const char *> V = tokenize(*Env);
  577. V.insert(V.end(), Args.begin(), Args.end());
  578. return parse(V);
  579. }
  580. std::vector<const char *> ArgParser::tokenize(StringRef S) {
  581. SmallVector<const char *, 16> Tokens;
  582. BumpPtrStringSaver Saver(AllocAux);
  583. llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
  584. return std::vector<const char *>(Tokens.begin(), Tokens.end());
  585. }
  586. // Creates a new command line by replacing options starting with '@'
  587. // character. '@<filename>' is replaced by the file's contents.
  588. ErrorOr<std::vector<const char *>>
  589. ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
  590. SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());
  591. BumpPtrStringSaver Saver(AllocAux);
  592. ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens);
  593. return std::vector<const char *>(Tokens.begin(), Tokens.end());
  594. }
  595. void printHelp(const char *Argv0) {
  596. COFFOptTable Table;
  597. Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false);
  598. }
  599. } // namespace coff
  600. } // namespace lld