Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/MinGW.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- MinGW.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
#include "MinGW.h"
10
#include "SymbolTable.h"
11
#include "lld/Common/ErrorHandler.h"
12
#include "llvm/Object/COFF.h"
13
#include "llvm/Support/Path.h"
14
#include "llvm/Support/raw_ostream.h"
15
16
using namespace lld;
17
using namespace lld::coff;
18
using namespace llvm;
19
using namespace llvm::COFF;
20
21
15
AutoExporter::AutoExporter() {
22
15
  excludeLibs = {
23
15
      "libgcc",
24
15
      "libgcc_s",
25
15
      "libstdc++",
26
15
      "libmingw32",
27
15
      "libmingwex",
28
15
      "libg2c",
29
15
      "libsupc++",
30
15
      "libobjc",
31
15
      "libgcj",
32
15
      "libclang_rt.builtins",
33
15
      "libclang_rt.builtins-aarch64",
34
15
      "libclang_rt.builtins-arm",
35
15
      "libclang_rt.builtins-i386",
36
15
      "libclang_rt.builtins-x86_64",
37
15
      "libc++",
38
15
      "libc++abi",
39
15
      "libunwind",
40
15
      "libmsvcrt",
41
15
      "libucrtbase",
42
15
  };
43
15
44
15
  excludeObjects = {
45
15
      "crt0.o",    "crt1.o",  "crt1u.o", "crt2.o",  "crt2u.o",    "dllcrt1.o",
46
15
      "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
47
15
  };
48
15
49
15
  excludeSymbolPrefixes = {
50
15
      // Import symbols
51
15
      "__imp_",
52
15
      "__IMPORT_DESCRIPTOR_",
53
15
      // Extra import symbols from GNU import libraries
54
15
      "__nm_",
55
15
      // C++ symbols
56
15
      "__rtti_",
57
15
      "__builtin_",
58
15
      // Artifical symbols such as .refptr
59
15
      ".",
60
15
  };
61
15
62
15
  excludeSymbolSuffixes = {
63
15
      "_iname",
64
15
      "_NULL_THUNK_DATA",
65
15
  };
66
15
67
15
  if (config->machine == I386) {
68
4
    excludeSymbols = {
69
4
        "__NULL_IMPORT_DESCRIPTOR",
70
4
        "__pei386_runtime_relocator",
71
4
        "_do_pseudo_reloc",
72
4
        "_impure_ptr",
73
4
        "__impure_ptr",
74
4
        "__fmode",
75
4
        "_environ",
76
4
        "___dso_handle",
77
4
        // These are the MinGW names that differ from the standard
78
4
        // ones (lacking an extra underscore).
79
4
        "_DllMain@12",
80
4
        "_DllEntryPoint@12",
81
4
        "_DllMainCRTStartup@12",
82
4
    };
83
4
    excludeSymbolPrefixes.insert("__head_");
84
11
  } else {
85
11
    excludeSymbols = {
86
11
        "__NULL_IMPORT_DESCRIPTOR",
87
11
        "_pei386_runtime_relocator",
88
11
        "do_pseudo_reloc",
89
11
        "impure_ptr",
90
11
        "_impure_ptr",
91
11
        "_fmode",
92
11
        "environ",
93
11
        "__dso_handle",
94
11
        // These are the MinGW names that differ from the standard
95
11
        // ones (lacking an extra underscore).
96
11
        "DllMain",
97
11
        "DllEntryPoint",
98
11
        "DllMainCRTStartup",
99
11
    };
100
11
    excludeSymbolPrefixes.insert("_head_");
101
11
  }
102
15
}
103
104
1
void AutoExporter::addWholeArchive(StringRef path) {
105
1
  StringRef libName = sys::path::filename(path);
106
1
  // Drop the file extension, to match the processing below.
107
1
  libName = libName.substr(0, libName.rfind('.'));
108
1
  excludeLibs.erase(libName);
109
1
}
110
111
263
bool AutoExporter::shouldExport(Defined *sym) const {
112
263
  if (!sym || 
!sym->isLive()257
||
!sym->getChunk()251
)
113
217
    return false;
114
46
115
46
  // Only allow the symbol kinds that make sense to export; in particular,
116
46
  // disallow import symbols.
117
46
  if (!isa<DefinedRegular>(sym) && 
!isa<DefinedCommon>(sym)2
)
118
2
    return false;
119
44
  if (excludeSymbols.count(sym->getName()))
120
9
    return false;
121
35
122
35
  for (StringRef prefix : excludeSymbolPrefixes.keys())
123
230
    if (sym->getName().startswith(prefix))
124
4
      return false;
125
35
  
for (StringRef suffix : excludeSymbolSuffixes.keys())31
126
61
    if (sym->getName().endswith(suffix))
127
1
      return false;
128
31
129
31
  // If a corresponding __imp_ symbol exists and is defined, don't export it.
130
31
  
if (30
symtab->find(("__imp_" + sym->getName()).str())30
)
131
2
    return false;
132
28
133
28
  // Check that file is non-null before dereferencing it, symbols not
134
28
  // originating in regular object files probably shouldn't be exported.
135
28
  if (!sym->getFile())
136
0
    return false;
137
28
138
28
  StringRef libName = sys::path::filename(sym->getFile()->parentName);
139
28
140
28
  // Drop the file extension.
141
28
  libName = libName.substr(0, libName.rfind('.'));
142
28
  if (!libName.empty())
143
2
    return !excludeLibs.count(libName);
144
26
145
26
  StringRef fileName = sys::path::filename(sym->getFile()->getName());
146
26
  return !excludeObjects.count(fileName);
147
26
}
148
149
5
void coff::writeDefFile(StringRef name) {
150
5
  std::error_code ec;
151
5
  raw_fd_ostream os(name, ec, sys::fs::F_None);
152
5
  if (ec)
153
0
    fatal("cannot open " + name + ": " + ec.message());
154
5
155
5
  os << "EXPORTS\n";
156
10
  for (Export &e : config->exports) {
157
10
    os << "    " << e.exportName << " "
158
10
       << "@" << e.ordinal;
159
10
    if (auto *def = dyn_cast_or_null<Defined>(e.sym)) {
160
10
      if (def && def->getChunk() &&
161
10
          !(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
162
0
        os << " DATA";
163
10
    }
164
10
    os << "\n";
165
10
  }
166
5
}