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