Coverage Report

Created: 2019-07-24 05:18

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