Coverage Report

Created: 2019-05-22 02:55

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/MinGW/Driver.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- MinGW/Driver.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
// MinGW is a GNU development environment for Windows. It consists of GNU
10
// tools such as GCC and GNU ld. Unlike Cygwin, there's no POSIX-compatible
11
// layer, as it aims to be a native development toolchain.
12
//
13
// lld/MinGW is a drop-in replacement for GNU ld/MinGW.
14
//
15
// Being a native development tool, a MinGW linker is not very different from
16
// Microsoft link.exe, so a MinGW linker can be implemented as a thin wrapper
17
// for lld/COFF. This driver takes Unix-ish command line options, translates
18
// them to Windows-ish ones, and then passes them to lld/COFF.
19
//
20
// When this driver calls the lld/COFF driver, it passes a hidden option
21
// "-lldmingw" along with other user-supplied options, to run the lld/COFF
22
// linker in "MinGW mode".
23
//
24
// There are subtle differences between MS link.exe and GNU ld/MinGW, and GNU
25
// ld/MinGW implements a few GNU-specific features. Such features are directly
26
// implemented in lld/COFF and enabled only when the linker is running in MinGW
27
// mode.
28
//
29
//===----------------------------------------------------------------------===//
30
31
#include "lld/Common/Driver.h"
32
#include "lld/Common/ErrorHandler.h"
33
#include "lld/Common/Version.h"
34
#include "llvm/ADT/ArrayRef.h"
35
#include "llvm/ADT/Optional.h"
36
#include "llvm/ADT/StringExtras.h"
37
#include "llvm/ADT/StringRef.h"
38
#include "llvm/Option/Arg.h"
39
#include "llvm/Option/ArgList.h"
40
#include "llvm/Option/Option.h"
41
#include "llvm/Support/CommandLine.h"
42
#include "llvm/Support/FileSystem.h"
43
#include "llvm/Support/Path.h"
44
45
#if !defined(_MSC_VER) && !defined(__MINGW32__)
46
#include <unistd.h>
47
#endif
48
49
using namespace lld;
50
using namespace llvm;
51
52
// Create OptTable
53
enum {
54
  OPT_INVALID = 0,
55
#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
56
#include "Options.inc"
57
#undef OPTION
58
};
59
60
// Create prefix string literals used in Options.td
61
#define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
62
#include "Options.inc"
63
#undef PREFIX
64
65
// Create table mapping all options defined in Options.td
66
static const opt::OptTable::Info InfoTable[] = {
67
#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
68
  {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
69
   X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
70
#include "Options.inc"
71
#undef OPTION
72
};
73
74
namespace {
75
class MinGWOptTable : public opt::OptTable {
76
public:
77
36
  MinGWOptTable() : OptTable(InfoTable, false) {}
78
  opt::InputArgList parse(ArrayRef<const char *> Argv);
79
};
80
} // namespace
81
82
0
static void printHelp(const char *Argv0) {
83
0
  MinGWOptTable().PrintHelp(
84
0
      outs(), (std::string(Argv0) + " [options] file...").c_str(), "lld",
85
0
      false /*ShowHidden*/, true /*ShowAllAliases*/);
86
0
  outs() << "\n";
87
0
}
88
89
36
opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> Argv) {
90
36
  unsigned MissingIndex;
91
36
  unsigned MissingCount;
92
36
93
36
  SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
94
36
  opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
95
36
96
36
  if (MissingCount)
97
0
    fatal(StringRef(Args.getArgString(MissingIndex)) + ": missing argument");
98
36
  for (auto *Arg : Args.filtered(OPT_UNKNOWN))
99
0
    fatal("unknown argument: " + Arg->getSpelling());
100
36
  return Args;
101
36
}
102
103
// Find a file by concatenating given paths.
104
1
static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {
105
1
  SmallString<128> S;
106
1
  sys::path::append(S, Path1, Path2);
107
1
  if (sys::fs::exists(S))
108
1
    return S.str().str();
109
0
  return None;
110
0
}
111
112
// This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths.
113
static std::string
114
1
searchLibrary(StringRef Name, ArrayRef<StringRef> SearchPaths, bool BStatic) {
115
1
  if (Name.startswith(":")) {
116
0
    for (StringRef Dir : SearchPaths)
117
0
      if (Optional<std::string> S = findFile(Dir, Name.substr(1)))
118
0
        return *S;
119
0
    fatal("unable to find library -l" + Name);
120
1
  }
121
1
122
1
  for (StringRef Dir : SearchPaths) {
123
1
    if (!BStatic)
124
1
      if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a"))
125
1
        return *S;
126
0
    if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a"))
127
0
      return *S;
128
0
  }
129
1
  
fatal("unable to find library -l" + Name)0
;
130
1
}
131
132
// Convert Unix-ish command line arguments to Windows-ish ones and
133
// then call coff::link.
134
36
bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) {
135
36
  MinGWOptTable Parser;
136
36
  opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
137
36
138
36
  if (Args.hasArg(OPT_help)) {
139
0
    printHelp(ArgsArr[0]);
140
0
    return true;
141
0
  }
142
36
143
36
  // A note about "compatible with GNU linkers" message: this is a hack for
144
36
  // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and
145
36
  // still the newest version in March 2017) or earlier to recognize LLD as
146
36
  // a GNU compatible linker. As long as an output for the -v option
147
36
  // contains "GNU" or "with BFD", they recognize us as GNU-compatible.
148
36
  if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version))
149
1
    message(getLLDVersion() + " (compatible with GNU linkers)");
150
36
151
36
  // The behavior of -v or --version is a bit strange, but this is
152
36
  // needed for compatibility with GNU linkers.
153
36
  if (Args.hasArg(OPT_v) && 
!Args.hasArg(OPT_INPUT)0
&&
!Args.hasArg(OPT_l)0
)
154
0
    return true;
155
36
  if (Args.hasArg(OPT_version))
156
1
    return true;
157
35
158
35
  if (!Args.hasArg(OPT_INPUT) && 
!Args.hasArg(OPT_l)1
)
159
0
    fatal("no input files");
160
35
161
35
  std::vector<std::string> LinkArgs;
162
371
  auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); };
163
35
164
35
  Add("lld-link");
165
35
  Add("-lldmingw");
166
35
167
35
  if (auto *A = Args.getLastArg(OPT_entry)) {
168
1
    StringRef S = A->getValue();
169
1
    if (Args.getLastArgValue(OPT_m) == "i386pe" && S.startswith("_"))
170
1
      Add("-entry:" + S.substr(1));
171
0
    else
172
0
      Add("-entry:" + S);
173
1
  }
174
35
175
35
  if (auto *A = Args.getLastArg(OPT_subs))
176
0
    Add("-subsystem:" + StringRef(A->getValue()));
177
35
  if (auto *A = Args.getLastArg(OPT_out_implib))
178
1
    Add("-implib:" + StringRef(A->getValue()));
179
35
  if (auto *A = Args.getLastArg(OPT_stack))
180
1
    Add("-stack:" + StringRef(A->getValue()));
181
35
  if (auto *A = Args.getLastArg(OPT_output_def))
182
1
    Add("-output-def:" + StringRef(A->getValue()));
183
35
  if (auto *A = Args.getLastArg(OPT_image_base))
184
1
    Add("-base:" + StringRef(A->getValue()));
185
35
  if (auto *A = Args.getLastArg(OPT_map))
186
1
    Add("-lldmap:" + StringRef(A->getValue()));
187
35
188
35
  if (auto *A = Args.getLastArg(OPT_o))
189
2
    Add("-out:" + StringRef(A->getValue()));
190
33
  else if (Args.hasArg(OPT_shared))
191
3
    Add("-out:a.dll");
192
30
  else
193
30
    Add("-out:a.exe");
194
35
195
35
  if (auto *A = Args.getLastArg(OPT_pdb)) {
196
1
    Add("-debug");
197
1
    StringRef V = A->getValue();
198
1
    if (!V.empty())
199
1
      Add("-pdb:" + V);
200
34
  } else if (Args.hasArg(OPT_strip_debug)) {
201
1
    Add("-debug:symtab");
202
33
  } else if (!Args.hasArg(OPT_strip_all)) {
203
32
    Add("-debug:dwarf");
204
32
  }
205
35
206
35
  if (Args.hasArg(OPT_shared))
207
3
    Add("-dll");
208
35
  if (Args.hasArg(OPT_verbose))
209
1
    Add("-verbose");
210
35
  if (Args.hasArg(OPT_exclude_all_symbols))
211
1
    Add("-exclude-all-symbols");
212
35
  if (Args.hasArg(OPT_export_all_symbols))
213
1
    Add("-export-all-symbols");
214
35
  if (Args.hasArg(OPT_large_address_aware))
215
0
    Add("-largeaddressaware");
216
35
  if (Args.hasArg(OPT_kill_at))
217
0
    Add("-kill-at");
218
35
  if (Args.hasArg(OPT_appcontainer))
219
0
    Add("-appcontainer");
220
35
221
35
  if (Args.getLastArgValue(OPT_m) != "thumb2pe" &&
222
35
      
Args.getLastArgValue(OPT_m) != "arm64pe"33
&&
!Args.hasArg(OPT_dynamicbase)31
)
223
30
    Add("-dynamicbase:no");
224
35
225
35
  if (Args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false))
226
1
    Add("-timestamp:0");
227
35
228
35
  if (Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false))
229
1
    Add("-opt:ref");
230
34
  else
231
34
    Add("-opt:noref");
232
35
233
35
  if (auto *A = Args.getLastArg(OPT_icf)) {
234
4
    StringRef S = A->getValue();
235
4
    if (S == "all")
236
0
      Add("-opt:icf");
237
4
    else if (S == "safe" || 
S == "none"2
)
238
4
      Add("-opt:noicf");
239
0
    else
240
0
      fatal("unknown parameter: --icf=" + S);
241
31
  } else {
242
31
    Add("-opt:noicf");
243
31
  }
244
35
245
35
  if (auto *A = Args.getLastArg(OPT_m)) {
246
35
    StringRef S = A->getValue();
247
35
    if (S == "i386pe")
248
3
      Add("-machine:x86");
249
32
    else if (S == "i386pep")
250
28
      Add("-machine:x64");
251
4
    else if (S == "thumb2pe")
252
2
      Add("-machine:arm");
253
2
    else if (S == "arm64pe")
254
2
      Add("-machine:arm64");
255
0
    else
256
0
      fatal("unknown parameter: -m" + S);
257
35
  }
258
35
259
35
  for (auto *A : Args.filtered(OPT_mllvm))
260
0
    Add("-mllvm:" + StringRef(A->getValue()));
261
35
262
35
  for (auto *A : Args.filtered(OPT_Xlink))
263
1
    Add(A->getValue());
264
35
265
35
  if (Args.getLastArgValue(OPT_m) == "i386pe")
266
3
    Add("-alternatename:__image_base__=___ImageBase");
267
32
  else
268
32
    Add("-alternatename:__image_base__=__ImageBase");
269
35
270
35
  for (auto *A : Args.filtered(OPT_require_defined))
271
4
    Add("-include:" + StringRef(A->getValue()));
272
35
273
35
  std::vector<StringRef> SearchPaths;
274
35
  for (auto *A : Args.filtered(OPT_L)) {
275
2
    SearchPaths.push_back(A->getValue());
276
2
    Add("-libpath:" + StringRef(A->getValue()));
277
2
  }
278
35
279
35
  StringRef Prefix = "";
280
35
  bool Static = false;
281
148
  for (auto *A : Args) {
282
148
    switch (A->getOption().getUnaliasedOption().getID()) {
283
148
    case OPT_INPUT:
284
40
      if (StringRef(A->getValue()).endswith_lower(".def"))
285
1
        Add("-def:" + StringRef(A->getValue()));
286
39
      else
287
39
        Add(Prefix + StringRef(A->getValue()));
288
40
      break;
289
148
    case OPT_l:
290
1
      Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static));
291
1
      break;
292
148
    case OPT_whole_archive:
293
2
      Prefix = "-wholearchive:";
294
2
      break;
295
148
    case OPT_no_whole_archive:
296
2
      Prefix = "";
297
2
      break;
298
148
    case OPT_Bstatic:
299
0
      Static = true;
300
0
      break;
301
148
    case OPT_Bdynamic:
302
0
      Static = false;
303
0
      break;
304
148
    }
305
148
  }
306
35
307
35
  if (Args.hasArg(OPT_verbose) || 
Args.hasArg(OPT__HASH_HASH_HASH)34
)
308
35
    outs() << llvm::join(LinkArgs, " ") << "\n";
309
35
310
35
  if (Args.hasArg(OPT__HASH_HASH_HASH))
311
35
    return true;
312
0
313
0
  // Repack vector of strings to vector of const char pointers for coff::link.
314
0
  std::vector<const char *> Vec;
315
0
  for (const std::string &S : LinkArgs)
316
0
    Vec.push_back(S.c_str());
317
0
  return coff::link(Vec, true);
318
0
}