Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/tools/lld/lld.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===//
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 the main function of the lld executable. The main
10
// function is a thin wrapper which dispatches to the platform specific
11
// driver.
12
//
13
// lld is a single executable that contains four different linkers for ELF,
14
// COFF, WebAssembly and Mach-O. The main function dispatches according to
15
// argv[0] (i.e. command name). The most common name for each target is shown
16
// below:
17
//
18
//  - ld.lld:    ELF (Unix)
19
//  - ld64:      Mach-O (macOS)
20
//  - lld-link:  COFF (Windows)
21
//  - ld-wasm:   WebAssembly
22
//
23
// lld can be invoked as "lld" along with "-flavor" option. This is for
24
// backward compatibility and not recommended.
25
//
26
//===----------------------------------------------------------------------===//
27
28
#include "lld/Common/Driver.h"
29
#include "lld/Common/Memory.h"
30
#include "llvm/ADT/STLExtras.h"
31
#include "llvm/ADT/SmallVector.h"
32
#include "llvm/ADT/StringSwitch.h"
33
#include "llvm/ADT/Triple.h"
34
#include "llvm/ADT/Twine.h"
35
#include "llvm/Support/CommandLine.h"
36
#include "llvm/Support/InitLLVM.h"
37
#include "llvm/Support/Path.h"
38
#include <cstdlib>
39
40
using namespace lld;
41
using namespace llvm;
42
using namespace llvm::sys;
43
44
enum Flavor {
45
  Invalid,
46
  Gnu,     // -flavor gnu
47
  WinLink, // -flavor link
48
  Darwin,  // -flavor darwin
49
  Wasm,    // -flavor wasm
50
};
51
52
0
LLVM_ATTRIBUTE_NORETURN static void die(const Twine &s) {
53
0
  errs() << s << "\n";
54
0
  exit(1);
55
0
}
56
57
4.92k
static Flavor getFlavor(StringRef s) {
58
4.92k
  return StringSwitch<Flavor>(s)
59
4.92k
      .CasesLower("ld", "ld.lld", "gnu", Gnu)
60
4.92k
      .CasesLower("wasm", "ld-wasm", Wasm)
61
4.92k
      .CaseLower("link", WinLink)
62
4.92k
      .CasesLower("ld64", "ld64.lld", "darwin", Darwin)
63
4.92k
      .Default(Invalid);
64
4.92k
}
65
66
2.99k
static cl::TokenizerCallback getDefaultQuotingStyle() {
67
2.99k
  if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32)
68
0
    return cl::TokenizeWindowsCommandLine;
69
2.99k
  return cl::TokenizeGNUCommandLine;
70
2.99k
}
71
72
130
static bool isPETargetName(StringRef s) {
73
130
  return s == "i386pe" || 
s == "i386pep"121
||
s == "thumb2pe"45
||
s == "arm64pe"43
;
74
130
}
75
76
3.11k
static bool isPETarget(std::vector<const char *> &v) {
77
18.4k
  for (auto it = v.begin(); it + 1 != v.end(); 
++it15.3k
) {
78
15.4k
    if (StringRef(*it) != "-m")
79
15.3k
      continue;
80
129
    return isPETargetName(*(it + 1));
81
129
  }
82
3.11k
  // Expand response files (arguments in the form of @<filename>)
83
3.11k
  // to allow detecting the -m argument from arguments in them.
84
3.11k
  SmallVector<const char *, 256> expandedArgs(v.data(), v.data() + v.size());
85
2.99k
  cl::ExpandResponseFiles(saver, getDefaultQuotingStyle(), expandedArgs);
86
18.1k
  for (auto it = expandedArgs.begin(); it + 1 != expandedArgs.end(); 
++it15.1k
) {
87
15.1k
    if (StringRef(*it) != "-m")
88
15.1k
      continue;
89
1
    return isPETargetName(*(it + 1));
90
1
  }
91
2.99k
  
return false2.98k
;
92
2.99k
}
93
94
4.23k
static Flavor parseProgname(StringRef progname) {
95
4.23k
#if __APPLE__
96
4.23k
  // Use Darwin driver for "ld" on Darwin.
97
4.23k
  if (progname == "ld")
98
1
    return Darwin;
99
4.23k
#endif
100
4.23k
101
4.23k
#if LLVM_ON_UNIX
102
4.23k
  // Use GNU driver for "ld" on other Unix-like system.
103
4.23k
  if (progname == "ld")
104
0
    return Gnu;
105
4.23k
#endif
106
4.23k
107
4.23k
  // Progname may be something like "lld-gnu". Parse it.
108
4.23k
  SmallVector<StringRef, 3> v;
109
4.23k
  progname.split(v, "-");
110
4.23k
  for (StringRef s : v)
111
4.92k
    if (Flavor f = getFlavor(s))
112
4.23k
      return f;
113
4.23k
  
return Invalid0
;
114
4.23k
}
115
116
4.23k
static Flavor parseFlavor(std::vector<const char *> &v) {
117
4.23k
  // Parse -flavor option.
118
4.23k
  if (v.size() > 1 && 
v[1] == StringRef("-flavor")4.22k
) {
119
0
    if (v.size() <= 2)
120
0
      die("missing arg value for '-flavor'");
121
0
    Flavor f = getFlavor(v[2]);
122
0
    if (f == Invalid)
123
0
      die("Unknown flavor: " + StringRef(v[2]));
124
0
    v.erase(v.begin() + 1, v.begin() + 3);
125
0
    return f;
126
0
  }
127
4.23k
128
4.23k
  // Deduct the flavor from argv[0].
129
4.23k
  StringRef arg0 = path::filename(v[0]);
130
4.23k
  if (arg0.endswith_lower(".exe"))
131
0
    arg0 = arg0.drop_back(4);
132
4.23k
  return parseProgname(arg0);
133
4.23k
}
134
135
// If this function returns true, lld calls _exit() so that it quickly
136
// exits without invoking destructors of globally allocated objects.
137
//
138
// We don't want to do that if we are running tests though, because
139
// doing that breaks leak sanitizer. So, lit sets this environment variable,
140
// and we use it to detect whether we are running tests or not.
141
4.14k
static bool canExitEarly() { return StringRef(getenv("LLD_IN_TEST")) != "1"; }
142
143
/// Universal linker main(). This linker emulates the gnu, darwin, or
144
/// windows linker based on the argv[0] or -flavor option.
145
4.23k
int main(int argc, const char **argv) {
146
4.23k
  InitLLVM x(argc, argv);
147
4.23k
148
4.23k
  std::vector<const char *> args(argv, argv + argc);
149
4.23k
  switch (parseFlavor(args)) {
150
4.23k
  case Gnu:
151
3.11k
    if (isPETarget(args))
152
89
      return !mingw::link(args);
153
3.03k
    return !elf::link(args, canExitEarly());
154
3.03k
  case WinLink:
155
689
    return !coff::link(args, canExitEarly());
156
3.03k
  case Darwin:
157
208
    return !mach_o::link(args, canExitEarly());
158
3.03k
  case Wasm:
159
217
    return !wasm::link(args, canExitEarly());
160
3.03k
  default:
161
0
    die("lld is a generic driver.\n"
162
0
        "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld"
163
0
        " (WebAssembly) instead");
164
4.23k
  }
165
4.23k
}