Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lld/COFF/MinGW.cpp
34870 views
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 "COFFLinkerContext.h"
11
#include "Driver.h"
12
#include "InputFiles.h"
13
#include "SymbolTable.h"
14
#include "llvm/ADT/DenseMap.h"
15
#include "llvm/ADT/DenseSet.h"
16
#include "llvm/Object/COFF.h"
17
#include "llvm/Support/Parallel.h"
18
#include "llvm/Support/Path.h"
19
#include "llvm/Support/TimeProfiler.h"
20
#include "llvm/Support/raw_ostream.h"
21
22
using namespace llvm;
23
using namespace llvm::COFF;
24
using namespace lld;
25
using namespace lld::coff;
26
27
AutoExporter::AutoExporter(
28
COFFLinkerContext &ctx,
29
const llvm::DenseSet<StringRef> &manualExcludeSymbols)
30
: manualExcludeSymbols(manualExcludeSymbols), ctx(ctx) {
31
excludeLibs = {
32
"libgcc",
33
"libgcc_s",
34
"libstdc++",
35
"libmingw32",
36
"libmingwex",
37
"libg2c",
38
"libsupc++",
39
"libobjc",
40
"libgcj",
41
"libclang_rt.builtins",
42
"libclang_rt.builtins-aarch64",
43
"libclang_rt.builtins-arm",
44
"libclang_rt.builtins-i386",
45
"libclang_rt.builtins-x86_64",
46
"libclang_rt.profile",
47
"libclang_rt.profile-aarch64",
48
"libclang_rt.profile-arm",
49
"libclang_rt.profile-i386",
50
"libclang_rt.profile-x86_64",
51
"libc++",
52
"libc++abi",
53
"libFortranRuntime",
54
"libFortranDecimal",
55
"libunwind",
56
"libmsvcrt",
57
"libucrtbase",
58
};
59
60
excludeObjects = {
61
"crt0.o", "crt1.o", "crt1u.o", "crt2.o", "crt2u.o", "dllcrt1.o",
62
"dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
63
};
64
65
excludeSymbolPrefixes = {
66
// Import symbols
67
"__imp_",
68
"__IMPORT_DESCRIPTOR_",
69
// Extra import symbols from GNU import libraries
70
"__nm_",
71
// C++ symbols
72
"__rtti_",
73
"__builtin_",
74
// Artificial symbols such as .refptr
75
".",
76
// profile generate symbols
77
"__profc_",
78
"__profd_",
79
"__profvp_",
80
};
81
82
excludeSymbolSuffixes = {
83
"_iname",
84
"_NULL_THUNK_DATA",
85
};
86
87
if (ctx.config.machine == I386) {
88
excludeSymbols = {
89
"__NULL_IMPORT_DESCRIPTOR",
90
"__pei386_runtime_relocator",
91
"_do_pseudo_reloc",
92
"_impure_ptr",
93
"__impure_ptr",
94
"__fmode",
95
"_environ",
96
"___dso_handle",
97
// These are the MinGW names that differ from the standard
98
// ones (lacking an extra underscore).
99
"_DllMain@12",
100
"_DllEntryPoint@12",
101
"_DllMainCRTStartup@12",
102
};
103
excludeSymbolPrefixes.insert("__head_");
104
} else {
105
excludeSymbols = {
106
"__NULL_IMPORT_DESCRIPTOR",
107
"_pei386_runtime_relocator",
108
"do_pseudo_reloc",
109
"impure_ptr",
110
"_impure_ptr",
111
"_fmode",
112
"environ",
113
"__dso_handle",
114
// These are the MinGW names that differ from the standard
115
// ones (lacking an extra underscore).
116
"DllMain",
117
"DllEntryPoint",
118
"DllMainCRTStartup",
119
};
120
excludeSymbolPrefixes.insert("_head_");
121
}
122
}
123
124
void AutoExporter::addWholeArchive(StringRef path) {
125
StringRef libName = sys::path::filename(path);
126
// Drop the file extension, to match the processing below.
127
libName = libName.substr(0, libName.rfind('.'));
128
excludeLibs.erase(libName);
129
}
130
131
void AutoExporter::addExcludedSymbol(StringRef symbol) {
132
excludeSymbols.insert(symbol);
133
}
134
135
bool AutoExporter::shouldExport(Defined *sym) const {
136
if (!sym || !sym->getChunk())
137
return false;
138
139
// Only allow the symbol kinds that make sense to export; in particular,
140
// disallow import symbols.
141
if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym))
142
return false;
143
if (excludeSymbols.count(sym->getName()) || manualExcludeSymbols.count(sym->getName()))
144
return false;
145
146
for (StringRef prefix : excludeSymbolPrefixes.keys())
147
if (sym->getName().starts_with(prefix))
148
return false;
149
for (StringRef suffix : excludeSymbolSuffixes.keys())
150
if (sym->getName().ends_with(suffix))
151
return false;
152
153
// If a corresponding __imp_ symbol exists and is defined, don't export it.
154
if (ctx.symtab.find(("__imp_" + sym->getName()).str()))
155
return false;
156
157
// Check that file is non-null before dereferencing it, symbols not
158
// originating in regular object files probably shouldn't be exported.
159
if (!sym->getFile())
160
return false;
161
162
StringRef libName = sys::path::filename(sym->getFile()->parentName);
163
164
// Drop the file extension.
165
libName = libName.substr(0, libName.rfind('.'));
166
if (!libName.empty())
167
return !excludeLibs.count(libName);
168
169
StringRef fileName = sys::path::filename(sym->getFile()->getName());
170
return !excludeObjects.count(fileName);
171
}
172
173
void lld::coff::writeDefFile(StringRef name,
174
const std::vector<Export> &exports) {
175
llvm::TimeTraceScope timeScope("Write .def file");
176
std::error_code ec;
177
raw_fd_ostream os(name, ec, sys::fs::OF_None);
178
if (ec)
179
fatal("cannot open " + name + ": " + ec.message());
180
181
os << "EXPORTS\n";
182
for (const Export &e : exports) {
183
os << " " << e.exportName << " "
184
<< "@" << e.ordinal;
185
if (auto *def = dyn_cast_or_null<Defined>(e.sym)) {
186
if (def && def->getChunk() &&
187
!(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
188
os << " DATA";
189
}
190
os << "\n";
191
}
192
}
193
194
static StringRef mangle(Twine sym, MachineTypes machine) {
195
assert(machine != IMAGE_FILE_MACHINE_UNKNOWN);
196
if (machine == I386)
197
return saver().save("_" + sym);
198
return saver().save(sym);
199
}
200
201
// Handles -wrap option.
202
//
203
// This function instantiates wrapper symbols. At this point, they seem
204
// like they are not being used at all, so we explicitly set some flags so
205
// that LTO won't eliminate them.
206
std::vector<WrappedSymbol>
207
lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
208
std::vector<WrappedSymbol> v;
209
DenseSet<StringRef> seen;
210
211
for (auto *arg : args.filtered(OPT_wrap)) {
212
StringRef name = arg->getValue();
213
if (!seen.insert(name).second)
214
continue;
215
216
Symbol *sym = ctx.symtab.findUnderscore(name);
217
if (!sym)
218
continue;
219
220
Symbol *real =
221
ctx.symtab.addUndefined(mangle("__real_" + name, ctx.config.machine));
222
Symbol *wrap =
223
ctx.symtab.addUndefined(mangle("__wrap_" + name, ctx.config.machine));
224
v.push_back({sym, real, wrap});
225
226
// These symbols may seem undefined initially, but don't bail out
227
// at symtab.reportUnresolvable() due to them, but let wrapSymbols
228
// below sort things out before checking finally with
229
// symtab.resolveRemainingUndefines().
230
sym->deferUndefined = true;
231
real->deferUndefined = true;
232
// We want to tell LTO not to inline symbols to be overwritten
233
// because LTO doesn't know the final symbol contents after renaming.
234
real->canInline = false;
235
sym->canInline = false;
236
237
// Tell LTO not to eliminate these symbols.
238
sym->isUsedInRegularObj = true;
239
if (!isa<Undefined>(wrap))
240
wrap->isUsedInRegularObj = true;
241
}
242
return v;
243
}
244
245
// Do renaming for -wrap by updating pointers to symbols.
246
//
247
// When this function is executed, only InputFiles and symbol table
248
// contain pointers to symbol objects. We visit them to replace pointers,
249
// so that wrapped symbols are swapped as instructed by the command line.
250
void lld::coff::wrapSymbols(COFFLinkerContext &ctx,
251
ArrayRef<WrappedSymbol> wrapped) {
252
DenseMap<Symbol *, Symbol *> map;
253
for (const WrappedSymbol &w : wrapped) {
254
map[w.sym] = w.wrap;
255
map[w.real] = w.sym;
256
if (Defined *d = dyn_cast<Defined>(w.wrap)) {
257
Symbol *imp = ctx.symtab.find(("__imp_" + w.sym->getName()).str());
258
// Create a new defined local import for the wrap symbol. If
259
// no imp prefixed symbol existed, there's no need for it.
260
// (We can't easily distinguish whether any object file actually
261
// referenced it or not, though.)
262
if (imp) {
263
DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
264
ctx, saver().save("__imp_" + w.wrap->getName()), d);
265
ctx.symtab.localImportChunks.push_back(wrapimp->getChunk());
266
map[imp] = wrapimp;
267
}
268
}
269
}
270
271
// Update pointers in input files.
272
parallelForEach(ctx.objFileInstances, [&](ObjFile *file) {
273
MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
274
for (auto &sym : syms)
275
if (Symbol *s = map.lookup(sym))
276
sym = s;
277
});
278
}
279
280