1 //===- MinGW.cpp ----------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 #include "COFFLinkerContext.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"
23 using namespace llvm::COFF
;
25 using namespace lld::coff
;
27 AutoExporter::AutoExporter(
28 COFFLinkerContext
&ctx
,
29 const llvm::DenseSet
<StringRef
> &manualExcludeSymbols
)
30 : manualExcludeSymbols(manualExcludeSymbols
), ctx(ctx
) {
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",
62 "crt0.o", "crt1.o", "crt1u.o", "crt2.o", "crt2u.o", "dllcrt1.o",
63 "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
66 excludeSymbolPrefixes
= {
69 "__IMPORT_DESCRIPTOR_",
70 // Extra import symbols from GNU import libraries
75 // Artificial symbols such as .refptr
77 // profile generate symbols
83 excludeSymbolSuffixes
= {
88 if (ctx
.config
.machine
== I386
) {
90 "__NULL_IMPORT_DESCRIPTOR",
91 "__pei386_runtime_relocator",
98 // These are the MinGW names that differ from the standard
99 // ones (lacking an extra underscore).
102 "_DllMainCRTStartup@12",
104 excludeSymbolPrefixes
.insert("__head_");
107 "__NULL_IMPORT_DESCRIPTOR",
108 "_pei386_runtime_relocator",
115 // These are the MinGW names that differ from the standard
116 // ones (lacking an extra underscore).
121 excludeSymbolPrefixes
.insert("_head_");
125 void AutoExporter::addWholeArchive(StringRef path
) {
126 StringRef libName
= sys::path::filename(path
);
127 // Drop the file extension, to match the processing below.
128 libName
= libName
.substr(0, libName
.rfind('.'));
129 excludeLibs
.erase(libName
);
132 void AutoExporter::addExcludedSymbol(StringRef symbol
) {
133 excludeSymbols
.insert(symbol
);
136 bool AutoExporter::shouldExport(Defined
*sym
) const {
137 if (!sym
|| !sym
->getChunk())
140 // Only allow the symbol kinds that make sense to export; in particular,
141 // disallow import symbols.
142 if (!isa
<DefinedRegular
>(sym
) && !isa
<DefinedCommon
>(sym
))
144 if (excludeSymbols
.count(sym
->getName()) || manualExcludeSymbols
.count(sym
->getName()))
147 for (StringRef prefix
: excludeSymbolPrefixes
.keys())
148 if (sym
->getName().starts_with(prefix
))
150 for (StringRef suffix
: excludeSymbolSuffixes
.keys())
151 if (sym
->getName().ends_with(suffix
))
154 // If a corresponding __imp_ symbol exists and is defined, don't export it.
155 if (ctx
.symtab
.find(("__imp_" + sym
->getName()).str()))
158 // Check that file is non-null before dereferencing it, symbols not
159 // originating in regular object files probably shouldn't be exported.
163 StringRef libName
= sys::path::filename(sym
->getFile()->parentName
);
165 // Drop the file extension.
166 libName
= libName
.substr(0, libName
.rfind('.'));
167 if (!libName
.empty())
168 return !excludeLibs
.count(libName
);
170 StringRef fileName
= sys::path::filename(sym
->getFile()->getName());
171 return !excludeObjects
.count(fileName
);
174 void lld::coff::writeDefFile(StringRef name
,
175 const std::vector
<Export
> &exports
) {
176 llvm::TimeTraceScope
timeScope("Write .def file");
178 raw_fd_ostream
os(name
, ec
, sys::fs::OF_None
);
180 fatal("cannot open " + name
+ ": " + ec
.message());
183 for (const Export
&e
: exports
) {
184 os
<< " " << e
.exportName
<< " "
186 if (auto *def
= dyn_cast_or_null
<Defined
>(e
.sym
)) {
187 if (def
&& def
->getChunk() &&
188 !(def
->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE
))
195 static StringRef
mangle(Twine sym
, MachineTypes machine
) {
196 assert(machine
!= IMAGE_FILE_MACHINE_UNKNOWN
);
198 return saver().save("_" + sym
);
199 return saver().save(sym
);
202 // Handles -wrap option.
204 // This function instantiates wrapper symbols. At this point, they seem
205 // like they are not being used at all, so we explicitly set some flags so
206 // that LTO won't eliminate them.
207 std::vector
<WrappedSymbol
>
208 lld::coff::addWrappedSymbols(COFFLinkerContext
&ctx
, opt::InputArgList
&args
) {
209 std::vector
<WrappedSymbol
> v
;
210 DenseSet
<StringRef
> seen
;
212 for (auto *arg
: args
.filtered(OPT_wrap
)) {
213 StringRef name
= arg
->getValue();
214 if (!seen
.insert(name
).second
)
217 Symbol
*sym
= ctx
.symtab
.findUnderscore(name
);
222 ctx
.symtab
.addUndefined(mangle("__real_" + name
, ctx
.config
.machine
));
224 ctx
.symtab
.addUndefined(mangle("__wrap_" + name
, ctx
.config
.machine
));
225 v
.push_back({sym
, real
, wrap
});
227 // These symbols may seem undefined initially, but don't bail out
228 // at symtab.reportUnresolvable() due to them, but let wrapSymbols
229 // below sort things out before checking finally with
230 // symtab.resolveRemainingUndefines().
231 sym
->deferUndefined
= true;
232 real
->deferUndefined
= true;
233 // We want to tell LTO not to inline symbols to be overwritten
234 // because LTO doesn't know the final symbol contents after renaming.
235 real
->canInline
= false;
236 sym
->canInline
= false;
238 // Tell LTO not to eliminate these symbols.
239 sym
->isUsedInRegularObj
= true;
240 if (!isa
<Undefined
>(wrap
))
241 wrap
->isUsedInRegularObj
= true;
246 // Do renaming for -wrap by updating pointers to symbols.
248 // When this function is executed, only InputFiles and symbol table
249 // contain pointers to symbol objects. We visit them to replace pointers,
250 // so that wrapped symbols are swapped as instructed by the command line.
251 void lld::coff::wrapSymbols(COFFLinkerContext
&ctx
,
252 ArrayRef
<WrappedSymbol
> wrapped
) {
253 DenseMap
<Symbol
*, Symbol
*> map
;
254 for (const WrappedSymbol
&w
: wrapped
) {
257 if (Defined
*d
= dyn_cast
<Defined
>(w
.wrap
)) {
258 Symbol
*imp
= ctx
.symtab
.find(("__imp_" + w
.sym
->getName()).str());
259 // Create a new defined local import for the wrap symbol. If
260 // no imp prefixed symbol existed, there's no need for it.
261 // (We can't easily distinguish whether any object file actually
262 // referenced it or not, though.)
264 DefinedLocalImport
*wrapimp
= make
<DefinedLocalImport
>(
265 ctx
, saver().save("__imp_" + w
.wrap
->getName()), d
);
266 ctx
.symtab
.localImportChunks
.push_back(wrapimp
->getChunk());
272 // Update pointers in input files.
273 parallelForEach(ctx
.objFileInstances
, [&](ObjFile
*file
) {
274 MutableArrayRef
<Symbol
*> syms
= file
->getMutableSymbols();
275 for (auto &sym
: syms
)
276 if (Symbol
*s
= map
.lookup(sym
))