Coverage Report

Created: 2019-05-22 02:55

/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
8
AutoExporter::AutoExporter() {
22
8
  ExcludeLibs = {
23
8
      "libgcc",
24
8
      "libgcc_s",
25
8
      "libstdc++",
26
8
      "libmingw32",
27
8
      "libmingwex",
28
8
      "libg2c",
29
8
      "libsupc++",
30
8
      "libobjc",
31
8
      "libgcj",
32
8
      "libclang_rt.builtins",
33
8
      "libclang_rt.builtins-aarch64",
34
8
      "libclang_rt.builtins-arm",
35
8
      "libclang_rt.builtins-i386",
36
8
      "libclang_rt.builtins-x86_64",
37
8
      "libc++",
38
8
      "libc++abi",
39
8
      "libunwind",
40
8
      "libmsvcrt",
41
8
      "libucrtbase",
42
8
  };
43
8
44
8
  ExcludeObjects = {
45
8
      "crt0.o",    "crt1.o",  "crt1u.o", "crt2.o",  "crt2u.o",    "dllcrt1.o",
46
8
      "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
47
8
  };
48
8
49
8
  ExcludeSymbolPrefixes = {
50
8
      // Import symbols
51
8
      "__imp_",
52
8
      "__IMPORT_DESCRIPTOR_",
53
8
      // Extra import symbols from GNU import libraries
54
8
      "__nm_",
55
8
      // C++ symbols
56
8
      "__rtti_",
57
8
      "__builtin_",
58
8
      // Artifical symbols such as .refptr
59
8
      ".",
60
8
  };
61
8
62
8
  ExcludeSymbolSuffixes = {
63
8
      "_iname",
64
8
      "_NULL_THUNK_DATA",
65
8
  };
66
8
67
8
  if (Config->Machine == I386) {
68
3
    ExcludeSymbols = {
69
3
        "__NULL_IMPORT_DESCRIPTOR",
70
3
        "__pei386_runtime_relocator",
71
3
        "_do_pseudo_reloc",
72
3
        "_impure_ptr",
73
3
        "__impure_ptr",
74
3
        "__fmode",
75
3
        "_environ",
76
3
        "___dso_handle",
77
3
        // These are the MinGW names that differ from the standard
78
3
        // ones (lacking an extra underscore).
79
3
        "_DllMain@12",
80
3
        "_DllEntryPoint@12",
81
3
        "_DllMainCRTStartup@12",
82
3
    };
83
3
    ExcludeSymbolPrefixes.insert("__head_");
84
5
  } else {
85
5
    ExcludeSymbols = {
86
5
        "__NULL_IMPORT_DESCRIPTOR",
87
5
        "_pei386_runtime_relocator",
88
5
        "do_pseudo_reloc",
89
5
        "impure_ptr",
90
5
        "_impure_ptr",
91
5
        "_fmode",
92
5
        "environ",
93
5
        "__dso_handle",
94
5
        // These are the MinGW names that differ from the standard
95
5
        // ones (lacking an extra underscore).
96
5
        "DllMain",
97
5
        "DllEntryPoint",
98
5
        "DllMainCRTStartup",
99
5
    };
100
5
    ExcludeSymbolPrefixes.insert("_head_");
101
5
  }
102
8
}
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
137
bool AutoExporter::shouldExport(Defined *Sym) const {
112
137
  if (!Sym || 
!Sym->isLive()134
||
!Sym->getChunk()134
)
113
115
    return false;
114
22
115
22
  // Only allow the symbol kinds that make sense to export; in particular,
116
22
  // disallow import symbols.
117
22
  if (!isa<DefinedRegular>(Sym) && 
!isa<DefinedCommon>(Sym)2
)
118
2
    return false;
119
20
  if (ExcludeSymbols.count(Sym->getName()))
120
4
    return false;
121
16
122
16
  for (StringRef Prefix : ExcludeSymbolPrefixes.keys())
123
112
    if (Sym->getName().startswith(Prefix))
124
0
      return false;
125
16
  for (StringRef Suffix : ExcludeSymbolSuffixes.keys())
126
32
    if (Sym->getName().endswith(Suffix))
127
0
      return false;
128
16
129
16
  // If a corresponding __imp_ symbol exists and is defined, don't export it.
130
16
  if (Symtab->find(("__imp_" + Sym->getName()).str()))
131
0
    return false;
132
16
133
16
  // Check that file is non-null before dereferencing it, symbols not
134
16
  // originating in regular object files probably shouldn't be exported.
135
16
  if (!Sym->getFile())
136
0
    return false;
137
16
138
16
  StringRef LibName = sys::path::filename(Sym->getFile()->ParentName);
139
16
140
16
  // Drop the file extension.
141
16
  LibName = LibName.substr(0, LibName.rfind('.'));
142
16
  if (!LibName.empty())
143
2
    return !ExcludeLibs.count(LibName);
144
14
145
14
  StringRef FileName = sys::path::filename(Sym->getFile()->getName());
146
14
  return !ExcludeObjects.count(FileName);
147
14
}
148
149
4
void coff::writeDefFile(StringRef Name) {
150
4
  std::error_code EC;
151
4
  raw_fd_ostream OS(Name, EC, sys::fs::F_None);
152
4
  if (EC)
153
0
    fatal("cannot open " + Name + ": " + EC.message());
154
4
155
4
  OS << "EXPORTS\n";
156
5
  for (Export &E : Config->Exports) {
157
5
    OS << "    " << E.ExportName << " "
158
5
       << "@" << E.Ordinal;
159
5
    if (auto *Def = dyn_cast_or_null<Defined>(E.Sym)) {
160
5
      if (Def && Def->getChunk() &&
161
5
          !(Def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
162
0
        OS << " DATA";
163
5
    }
164
5
    OS << "\n";
165
5
  }
166
4
}