Coverage Report

Created: 2019-01-21 03:01

/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 "llvm/ADT/ArrayRef.h"
34
#include "llvm/ADT/Optional.h"
35
#include "llvm/ADT/StringExtras.h"
36
#include "llvm/ADT/StringRef.h"
37
#include "llvm/Option/Arg.h"
38
#include "llvm/Option/ArgList.h"
39
#include "llvm/Option/Option.h"
40
#include "llvm/Support/CommandLine.h"
41
#include "llvm/Support/FileSystem.h"
42
#include "llvm/Support/Path.h"
43
44
#if !defined(_MSC_VER) && !defined(__MINGW32__)
45
#include <unistd.h>
46
#endif
47
48
using namespace lld;
49
using namespace llvm;
50
51
// Create OptTable
52
enum {
53
  OPT_INVALID = 0,
54
#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
55
#include "Options.inc"
56
#undef OPTION
57
};
58
59
// Create prefix string literals used in Options.td
60
#define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
61
#include "Options.inc"
62
#undef PREFIX
63
64
// Create table mapping all options defined in Options.td
65
static const opt::OptTable::Info InfoTable[] = {
66
#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
67
  {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
68
   X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
69
#include "Options.inc"
70
#undef OPTION
71
};
72
73
namespace {
74
class MinGWOptTable : public opt::OptTable {
75
public:
76
68
  MinGWOptTable() : OptTable(InfoTable, false) {}
77
  opt::InputArgList parse(ArrayRef<const char *> Argv);
78
};
79
} // namespace
80
81
68
opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> Argv) {
82
68
  unsigned MissingIndex;
83
68
  unsigned MissingCount;
84
68
85
68
  SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
86
68
  opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
87
68
88
68
  if (MissingCount)
89
0
    fatal(StringRef(Args.getArgString(MissingIndex)) + ": missing argument");
90
68
  for (auto *Arg : Args.filtered(OPT_UNKNOWN))
91
0
    fatal("unknown argument: " + Arg->getSpelling());
92
68
  if (!Args.hasArg(OPT_INPUT) && 
!Args.hasArg(OPT_l)3
)
93
0
    fatal("no input files");
94
68
  return Args;
95
68
}
96
97
// Find a file by concatenating given paths.
98
4
static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {
99
4
  SmallString<128> S;
100
4
  sys::path::append(S, Path1, Path2);
101
4
  if (sys::fs::exists(S))
102
4
    return S.str().str();
103
0
  return None;
104
0
}
105
106
// This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths.
107
static std::string
108
4
searchLibrary(StringRef Name, ArrayRef<StringRef> SearchPaths, bool BStatic) {
109
4
  if (Name.startswith(":")) {
110
0
    for (StringRef Dir : SearchPaths)
111
0
      if (Optional<std::string> S = findFile(Dir, Name.substr(1)))
112
0
        return *S;
113
0
    fatal("unable to find library -l" + Name);
114
4
  }
115
4
116
4
  for (StringRef Dir : SearchPaths) {
117
4
    if (!BStatic)
118
2
      if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a"))
119
2
        return *S;
120
2
    if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a"))
121
2
      return *S;
122
2
  }
123
4
  
fatal("unable to find library -l" + Name)0
;
124
4
}
125
126
// Convert Unix-ish command line arguments to Windows-ish ones and
127
// then call coff::link.
128
68
bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) {
129
68
  MinGWOptTable Parser;
130
68
  opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
131
68
132
68
  std::vector<std::string> LinkArgs;
133
722
  auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); };
134
68
135
68
  Add("lld-link");
136
68
  Add("-lldmingw");
137
68
138
68
  if (auto *A = Args.getLastArg(OPT_entry)) {
139
4
    StringRef S = A->getValue();
140
4
    if (Args.getLastArgValue(OPT_m) == "i386pe" && 
S.startswith("_")1
)
141
1
      Add("-entry:" + S.substr(1));
142
3
    else
143
3
      Add("-entry:" + S);
144
4
  }
145
68
146
68
  if (auto *A = Args.getLastArg(OPT_subs))
147
2
    Add("-subsystem:" + StringRef(A->getValue()));
148
68
  if (auto *A = Args.getLastArg(OPT_out_implib))
149
2
    Add("-implib:" + StringRef(A->getValue()));
150
68
  if (auto *A = Args.getLastArg(OPT_stack))
151
2
    Add("-stack:" + StringRef(A->getValue()));
152
68
  if (auto *A = Args.getLastArg(OPT_output_def))
153
1
    Add("-output-def:" + StringRef(A->getValue()));
154
68
  if (auto *A = Args.getLastArg(OPT_image_base))
155
2
    Add("-base:" + StringRef(A->getValue()));
156
68
  if (auto *A = Args.getLastArg(OPT_map))
157
4
    Add("-lldmap:" + StringRef(A->getValue()));
158
68
159
68
  if (auto *A = Args.getLastArg(OPT_o))
160
3
    Add("-out:" + StringRef(A->getValue()));
161
65
  else if (Args.hasArg(OPT_shared))
162
7
    Add("-out:a.dll");
163
58
  else
164
58
    Add("-out:a.exe");
165
68
166
68
  if (auto *A = Args.getLastArg(OPT_pdb)) {
167
1
    Add("-debug");
168
1
    Add("-pdb:" + StringRef(A->getValue()));
169
67
  } else if (Args.hasArg(OPT_strip_debug)) {
170
2
    Add("-debug:symtab");
171
65
  } else if (!Args.hasArg(OPT_strip_all)) {
172
63
    Add("-debug:dwarf");
173
63
  }
174
68
175
68
  if (Args.hasArg(OPT_shared))
176
7
    Add("-dll");
177
68
  if (Args.hasArg(OPT_verbose))
178
2
    Add("-verbose");
179
68
  if (Args.hasArg(OPT_export_all_symbols))
180
1
    Add("-export-all-symbols");
181
68
  if (Args.hasArg(OPT_large_address_aware))
182
1
    Add("-largeaddressaware");
183
68
  if (Args.hasArg(OPT_kill_at))
184
2
    Add("-kill-at");
185
68
186
68
  if (Args.getLastArgValue(OPT_m) != "thumb2pe" &&
187
68
      
Args.getLastArgValue(OPT_m) != "arm64pe"66
&&
!Args.hasArg(OPT_dynamicbase)64
)
188
62
    Add("-dynamicbase:no");
189
68
190
68
  if (Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false))
191
2
    Add("-opt:ref");
192
66
  else
193
66
    Add("-opt:noref");
194
68
195
68
  if (auto *A = Args.getLastArg(OPT_icf)) {
196
6
    StringRef S = A->getValue();
197
6
    if (S == "all")
198
2
      Add("-opt:icf");
199
4
    else if (S == "safe" || 
S == "none"2
)
200
4
      Add("-opt:noicf");
201
0
    else
202
0
      fatal("unknown parameter: --icf=" + S);
203
62
  } else {
204
62
    Add("-opt:noicf");
205
62
  }
206
68
207
68
  if (auto *A = Args.getLastArg(OPT_m)) {
208
68
    StringRef S = A->getValue();
209
68
    if (S == "i386pe")
210
7
      Add("-machine:x86");
211
61
    else if (S == "i386pep")
212
57
      Add("-machine:x64");
213
4
    else if (S == "thumb2pe")
214
2
      Add("-machine:arm");
215
2
    else if (S == "arm64pe")
216
2
      Add("-machine:arm64");
217
0
    else
218
0
      fatal("unknown parameter: -m" + S);
219
68
  }
220
68
221
68
  for (auto *A : Args.filtered(OPT_mllvm))
222
2
    Add("-mllvm:" + StringRef(A->getValue()));
223
68
224
68
  for (auto *A : Args.filtered(OPT_Xlink))
225
1
    Add(A->getValue());
226
68
227
68
  if (Args.getLastArgValue(OPT_m) == "i386pe")
228
7
    Add("-alternatename:__image_base__=___ImageBase");
229
61
  else
230
61
    Add("-alternatename:__image_base__=__ImageBase");
231
68
232
68
  for (auto *A : Args.filtered(OPT_require_defined))
233
4
    Add("-include:" + StringRef(A->getValue()));
234
68
235
68
  std::vector<StringRef> SearchPaths;
236
68
  for (auto *A : Args.filtered(OPT_L)) {
237
4
    SearchPaths.push_back(A->getValue());
238
4
    Add("-libpath:" + StringRef(A->getValue()));
239
4
  }
240
68
241
68
  StringRef Prefix = "";
242
68
  bool Static = false;
243
282
  for (auto *A : Args) {
244
282
    switch (A->getOption().getUnaliasedOption().getID()) {
245
282
    case OPT_INPUT:
246
72
      if (StringRef(A->getValue()).endswith_lower(".def"))
247
2
        Add("-def:" + StringRef(A->getValue()));
248
70
      else
249
70
        Add(Prefix + StringRef(A->getValue()));
250
72
      break;
251
282
    case OPT_l:
252
4
      Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static));
253
4
      break;
254
282
    case OPT_whole_archive:
255
2
      Prefix = "-wholearchive:";
256
2
      break;
257
282
    case OPT_no_whole_archive:
258
2
      Prefix = "";
259
2
      break;
260
282
    case OPT_Bstatic:
261
2
      Static = true;
262
2
      break;
263
282
    case OPT_Bdynamic:
264
1
      Static = false;
265
1
      break;
266
282
    }
267
282
  }
268
68
269
68
  if (Args.hasArg(OPT_verbose) || 
Args.hasArg(OPT__HASH_HASH_HASH)66
)
270
68
    outs() << llvm::join(LinkArgs, " ") << "\n";
271
68
272
68
  if (Args.hasArg(OPT__HASH_HASH_HASH))
273
68
    return true;
274
0
275
0
  // Repack vector of strings to vector of const char pointers for coff::link.
276
0
  std::vector<const char *> Vec;
277
0
  for (const std::string &S : LinkArgs)
278
0
    Vec.push_back(S.c_str());
279
0
  return coff::link(Vec, true);
280
0
}