xref: /freebsd/contrib/llvm-project/lld/COFF/MinGW.cpp (revision e9e8876a4d6afc1ad5315faaa191b25121a813d7)
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 "Driver.h"
11 #include "InputFiles.h"
12 #include "SymbolTable.h"
13 #include "lld/Common/ErrorHandler.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/raw_ostream.h"
20 
21 using namespace llvm;
22 using namespace llvm::COFF;
23 using namespace lld;
24 using namespace lld::coff;
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",
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",
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       ".",
70       // profile generate symbols
71       "__profc_",
72       "__profd_",
73       "__profvp_",
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 {
126   if (!sym || !sym->getChunk())
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 
163 void lld::coff::writeDefFile(StringRef name) {
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 }
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 }
264