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