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