blob: 0c7a8605cd59ab5bcc7c7db4301bf1787d839ab7 [file] [log] [blame]
Martin Storsjoe1f894d2017-10-19 19:49:381//===- MinGW.cpp ----------------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:563// 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
Martin Storsjoe1f894d2017-10-19 19:49:386//
7//===----------------------------------------------------------------------===//
8
9#include "MinGW.h"
Amy Huang6f7483b2021-09-16 23:48:2610#include "COFFLinkerContext.h"
Martin Storsjö3785a412020-10-06 10:54:4911#include "Driver.h"
12#include "InputFiles.h"
Martin Storsjo00107072017-11-29 05:50:4913#include "SymbolTable.h"
Martin Storsjö3785a412020-10-06 10:54:4914#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/DenseSet.h"
Martin Storsjoe1f894d2017-10-19 19:49:3816#include "llvm/Object/COFF.h"
Martin Storsjö3785a412020-10-06 10:54:4917#include "llvm/Support/Parallel.h"
Martin Storsjoe1f894d2017-10-19 19:49:3818#include "llvm/Support/Path.h"
Alexandre Ganea356139b2023-10-06 02:33:5819#include "llvm/Support/TimeProfiler.h"
Martin Storsjoe1f894d2017-10-19 19:49:3820#include "llvm/Support/raw_ostream.h"
21
Martin Storsjoe1f894d2017-10-19 19:49:3822using namespace llvm;
23using namespace llvm::COFF;
Reid Kleckner8a310f42020-02-20 01:05:4224using namespace lld;
25using namespace lld::coff;
Fangrui Songd79c3be2019-10-10 11:27:5826
Martin Storsjö5d513ef2022-07-17 21:11:3727AutoExporter::AutoExporter(
Jacek Cabanf7294772025-02-06 21:25:5328 SymbolTable &symtab, const llvm::DenseSet<StringRef> &manualExcludeSymbols)
29 : manualExcludeSymbols(manualExcludeSymbols), symtab(symtab) {
Rui Ueyama136d27a2019-07-11 05:40:3030 excludeLibs = {
Rui Ueyama659f2752019-02-19 22:06:4431 "libgcc",
32 "libgcc_s",
33 "libstdc++",
34 "libmingw32",
35 "libmingwex",
36 "libg2c",
37 "libsupc++",
38 "libobjc",
39 "libgcj",
40 "libclang_rt.builtins",
41 "libclang_rt.builtins-aarch64",
42 "libclang_rt.builtins-arm",
43 "libclang_rt.builtins-i386",
44 "libclang_rt.builtins-x86_64",
Peiyuan Songda324f92020-07-30 20:32:3745 "libclang_rt.profile",
46 "libclang_rt.profile-aarch64",
47 "libclang_rt.profile-arm",
48 "libclang_rt.profile-i386",
49 "libclang_rt.profile-x86_64",
Rui Ueyama659f2752019-02-19 22:06:4450 "libc++",
51 "libc++abi",
Michael Kruse5c8c2b32025-02-08 17:02:5452 "libflang_rt.runtime",
Rui Ueyama659f2752019-02-19 22:06:4453 "libunwind",
54 "libmsvcrt",
Martin Storsjöaf93db92025-03-21 13:33:2555 "libmsvcrt-os",
Rui Ueyama659f2752019-02-19 22:06:4456 "libucrtbase",
Martin Storsjöaf93db92025-03-21 13:33:2557 "libucrt",
58 "libucrtapp",
59 "libpthread",
60 "libwinpthread",
Rui Ueyama659f2752019-02-19 22:06:4461 };
62
Rui Ueyama136d27a2019-07-11 05:40:3063 excludeObjects = {
Rui Ueyama659f2752019-02-19 22:06:4464 "crt0.o", "crt1.o", "crt1u.o", "crt2.o", "crt2u.o", "dllcrt1.o",
65 "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
66 };
67
Rui Ueyama136d27a2019-07-11 05:40:3068 excludeSymbolPrefixes = {
Martin Storsjo32e651e2018-09-26 06:13:4769 // Import symbols
70 "__imp_",
71 "__IMPORT_DESCRIPTOR_",
72 // Extra import symbols from GNU import libraries
73 "__nm_",
74 // C++ symbols
75 "__rtti_",
76 "__builtin_",
Nico Weber79a84762019-10-10 02:04:5677 // Artificial symbols such as .refptr
Martin Storsjo32e651e2018-09-26 06:13:4778 ".",
Peiyuan Songda324f92020-07-30 20:32:3779 // profile generate symbols
80 "__profc_",
81 "__profd_",
82 "__profvp_",
Martin Storsjo32e651e2018-09-26 06:13:4783 };
Rui Ueyama659f2752019-02-19 22:06:4484
Rui Ueyama136d27a2019-07-11 05:40:3085 excludeSymbolSuffixes = {
Martin Storsjo32e651e2018-09-26 06:13:4786 "_iname",
87 "_NULL_THUNK_DATA",
88 };
Rui Ueyama659f2752019-02-19 22:06:4489
Jacek Cabanf7294772025-02-06 21:25:5390 if (symtab.machine == I386) {
Rui Ueyama136d27a2019-07-11 05:40:3091 excludeSymbols = {
Martin Storsjoe1f894d2017-10-19 19:49:3892 "__NULL_IMPORT_DESCRIPTOR",
93 "__pei386_runtime_relocator",
94 "_do_pseudo_reloc",
95 "_impure_ptr",
96 "__impure_ptr",
97 "__fmode",
98 "_environ",
99 "___dso_handle",
Jacek Cabanabd31b42025-02-07 14:52:39100 "__load_config_used",
Martin Storsjoe1f894d2017-10-19 19:49:38101 // These are the MinGW names that differ from the standard
102 // ones (lacking an extra underscore).
103 "_DllMain@12",
104 "_DllEntryPoint@12",
105 "_DllMainCRTStartup@12",
106 };
Rui Ueyama136d27a2019-07-11 05:40:30107 excludeSymbolPrefixes.insert("__head_");
Rui Ueyamac1214012017-11-22 09:06:27108 } else {
Rui Ueyama136d27a2019-07-11 05:40:30109 excludeSymbols = {
Martin Storsjo5fefad72018-09-18 07:22:05110 "__NULL_IMPORT_DESCRIPTOR",
Martin Storsjoe1f894d2017-10-19 19:49:38111 "_pei386_runtime_relocator",
112 "do_pseudo_reloc",
113 "impure_ptr",
114 "_impure_ptr",
115 "_fmode",
116 "environ",
117 "__dso_handle",
Jacek Cabanabd31b42025-02-07 14:52:39118 "_load_config_used",
Martin Storsjoe1f894d2017-10-19 19:49:38119 // These are the MinGW names that differ from the standard
120 // ones (lacking an extra underscore).
121 "DllMain",
122 "DllEntryPoint",
123 "DllMainCRTStartup",
124 };
Rui Ueyama136d27a2019-07-11 05:40:30125 excludeSymbolPrefixes.insert("_head_");
Rui Ueyamac1214012017-11-22 09:06:27126 }
Jacek Cabanabd31b42025-02-07 14:52:39127 if (symtab.isEC()) {
128 excludeSymbols.insert("__chpe_metadata");
129 excludeSymbolPrefixes.insert("__os_arm64x_");
130 }
Martin Storsjoa47957a2018-09-04 20:56:56131}
Martin Storsjoe1f894d2017-10-19 19:49:38132
Rui Ueyama136d27a2019-07-11 05:40:30133void AutoExporter::addWholeArchive(StringRef path) {
134 StringRef libName = sys::path::filename(path);
Martin Storsjoa47957a2018-09-04 20:56:56135 // Drop the file extension, to match the processing below.
Rui Ueyama136d27a2019-07-11 05:40:30136 libName = libName.substr(0, libName.rfind('.'));
137 excludeLibs.erase(libName);
Martin Storsjoa47957a2018-09-04 20:56:56138}
139
Martin Storsjöd1da6462022-07-18 20:43:02140void AutoExporter::addExcludedSymbol(StringRef symbol) {
141 excludeSymbols.insert(symbol);
142}
143
Amy Huang5a58b192023-01-10 04:37:28144bool AutoExporter::shouldExport(Defined *sym) const {
Martin Storsjö2b01a412021-04-29 08:57:33145 if (!sym || !sym->getChunk())
Martin Storsjoe1f894d2017-10-19 19:49:38146 return false;
Rui Ueyamac1214012017-11-22 09:06:27147
Martin Storsjofe3eda92017-11-16 07:22:44148 // Only allow the symbol kinds that make sense to export; in particular,
149 // disallow import symbols.
Rui Ueyama136d27a2019-07-11 05:40:30150 if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym))
Martin Storsjofe3eda92017-11-16 07:22:44151 return false;
Martin Storsjö5d513ef2022-07-17 21:11:37152 if (excludeSymbols.count(sym->getName()) || manualExcludeSymbols.count(sym->getName()))
Martin Storsjoe1f894d2017-10-19 19:49:38153 return false;
Rui Ueyamac1214012017-11-22 09:06:27154
Rui Ueyama136d27a2019-07-11 05:40:30155 for (StringRef prefix : excludeSymbolPrefixes.keys())
Fangrui Song8d85c962023-06-05 21:36:19156 if (sym->getName().starts_with(prefix))
Martin Storsjo32e651e2018-09-26 06:13:47157 return false;
Rui Ueyama136d27a2019-07-11 05:40:30158 for (StringRef suffix : excludeSymbolSuffixes.keys())
Fangrui Song8d85c962023-06-05 21:36:19159 if (sym->getName().ends_with(suffix))
Martin Storsjo32e651e2018-09-26 06:13:47160 return false;
Martin Storsjo00107072017-11-29 05:50:49161
162 // If a corresponding __imp_ symbol exists and is defined, don't export it.
Jacek Cabanf7294772025-02-06 21:25:53163 if (symtab.find(("__imp_" + sym->getName()).str()))
Martin Storsjo00107072017-11-29 05:50:49164 return false;
165
Martin Storsjofe3eda92017-11-16 07:22:44166 // Check that file is non-null before dereferencing it, symbols not
167 // originating in regular object files probably shouldn't be exported.
Rui Ueyama136d27a2019-07-11 05:40:30168 if (!sym->getFile())
Martin Storsjofe3eda92017-11-16 07:22:44169 return false;
Rui Ueyamac1214012017-11-22 09:06:27170
Rui Ueyama136d27a2019-07-11 05:40:30171 StringRef libName = sys::path::filename(sym->getFile()->parentName);
Rui Ueyamac1214012017-11-22 09:06:27172
Martin Storsjoe1f894d2017-10-19 19:49:38173 // Drop the file extension.
Rui Ueyama136d27a2019-07-11 05:40:30174 libName = libName.substr(0, libName.rfind('.'));
175 if (!libName.empty())
176 return !excludeLibs.count(libName);
Rui Ueyamac1214012017-11-22 09:06:27177
Rui Ueyama136d27a2019-07-11 05:40:30178 StringRef fileName = sys::path::filename(sym->getFile()->getName());
179 return !excludeObjects.count(fileName);
Martin Storsjoe1f894d2017-10-19 19:49:38180}
181
Fangrui Song983f88c12024-12-06 04:41:36182void lld::coff::writeDefFile(COFFLinkerContext &ctx, StringRef name,
Amy Huang5a58b192023-01-10 04:37:28183 const std::vector<Export> &exports) {
Alexandre Ganea356139b2023-10-06 02:33:58184 llvm::TimeTraceScope timeScope("Write .def file");
Rui Ueyama136d27a2019-07-11 05:40:30185 std::error_code ec;
Fangrui Songd9b948b2019-08-05 05:43:48186 raw_fd_ostream os(name, ec, sys::fs::OF_None);
Rui Ueyama136d27a2019-07-11 05:40:30187 if (ec)
Fangrui Song983f88c12024-12-06 04:41:36188 Fatal(ctx) << "cannot open " << name << ": " << ec.message();
Martin Storsjoe1f894d2017-10-19 19:49:38189
Rui Ueyama136d27a2019-07-11 05:40:30190 os << "EXPORTS\n";
Amy Huang5a58b192023-01-10 04:37:28191 for (const Export &e : exports) {
Rui Ueyama136d27a2019-07-11 05:40:30192 os << " " << e.exportName << " "
193 << "@" << e.ordinal;
194 if (auto *def = dyn_cast_or_null<Defined>(e.sym)) {
195 if (def && def->getChunk() &&
196 !(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
197 os << " DATA";
Martin Storsjoe1f894d2017-10-19 19:49:38198 }
Rui Ueyama136d27a2019-07-11 05:40:30199 os << "\n";
Martin Storsjoe1f894d2017-10-19 19:49:38200 }
201}
Martin Storsjö3785a412020-10-06 10:54:49202
Amy Huang5a58b192023-01-10 04:37:28203static StringRef mangle(Twine sym, MachineTypes machine) {
204 assert(machine != IMAGE_FILE_MACHINE_UNKNOWN);
205 if (machine == I386)
Alexandre Ganea83d59e02022-01-20 19:53:18206 return saver().save("_" + sym);
207 return saver().save(sym);
Martin Storsjö3785a412020-10-06 10:54:49208}
209
210// Handles -wrap option.
211//
212// This function instantiates wrapper symbols. At this point, they seem
213// like they are not being used at all, so we explicitly set some flags so
214// that LTO won't eliminate them.
Jacek Caban94d95632025-02-10 21:52:11215void lld::coff::addWrappedSymbols(SymbolTable &symtab,
216 opt::InputArgList &args) {
Martin Storsjö3785a412020-10-06 10:54:49217 std::vector<WrappedSymbol> v;
218 DenseSet<StringRef> seen;
219
220 for (auto *arg : args.filtered(OPT_wrap)) {
221 StringRef name = arg->getValue();
222 if (!seen.insert(name).second)
223 continue;
224
Jacek Caban94d95632025-02-10 21:52:11225 Symbol *sym = symtab.findUnderscore(name);
Martin Storsjö3785a412020-10-06 10:54:49226 if (!sym)
227 continue;
228
Amy Huang5a58b192023-01-10 04:37:28229 Symbol *real =
Jacek Caban94d95632025-02-10 21:52:11230 symtab.addUndefined(mangle("__real_" + name, symtab.machine));
Amy Huang5a58b192023-01-10 04:37:28231 Symbol *wrap =
Jacek Caban94d95632025-02-10 21:52:11232 symtab.addUndefined(mangle("__wrap_" + name, symtab.machine));
Martin Storsjö3785a412020-10-06 10:54:49233 v.push_back({sym, real, wrap});
234
235 // These symbols may seem undefined initially, but don't bail out
Amy Huang6f7483b2021-09-16 23:48:26236 // at symtab.reportUnresolvable() due to them, but let wrapSymbols
Martin Storsjö3785a412020-10-06 10:54:49237 // below sort things out before checking finally with
Amy Huang6f7483b2021-09-16 23:48:26238 // symtab.resolveRemainingUndefines().
Martin Storsjö3785a412020-10-06 10:54:49239 sym->deferUndefined = true;
240 real->deferUndefined = true;
241 // We want to tell LTO not to inline symbols to be overwritten
242 // because LTO doesn't know the final symbol contents after renaming.
243 real->canInline = false;
244 sym->canInline = false;
245
246 // Tell LTO not to eliminate these symbols.
247 sym->isUsedInRegularObj = true;
248 if (!isa<Undefined>(wrap))
249 wrap->isUsedInRegularObj = true;
250 }
Jacek Caban94d95632025-02-10 21:52:11251 symtab.wrapped = std::move(v);
Martin Storsjö3785a412020-10-06 10:54:49252}
253
254// Do renaming for -wrap by updating pointers to symbols.
255//
256// When this function is executed, only InputFiles and symbol table
257// contain pointers to symbol objects. We visit them to replace pointers,
258// so that wrapped symbols are swapped as instructed by the command line.
Jacek Caban94d95632025-02-10 21:52:11259void lld::coff::wrapSymbols(SymbolTable &symtab) {
Martin Storsjö3785a412020-10-06 10:54:49260 DenseMap<Symbol *, Symbol *> map;
Jacek Caban94d95632025-02-10 21:52:11261 for (const WrappedSymbol &w : symtab.wrapped) {
Martin Storsjö3785a412020-10-06 10:54:49262 map[w.sym] = w.wrap;
263 map[w.real] = w.sym;
Martin Storsjö0b2d84f2020-11-17 14:05:29264 if (Defined *d = dyn_cast<Defined>(w.wrap)) {
Jacek Caban94d95632025-02-10 21:52:11265 Symbol *imp = symtab.find(("__imp_" + w.sym->getName()).str());
Martin Storsjö0b2d84f2020-11-17 14:05:29266 // Create a new defined local import for the wrap symbol. If
267 // no imp prefixed symbol existed, there's no need for it.
268 // (We can't easily distinguish whether any object file actually
269 // referenced it or not, though.)
270 if (imp) {
271 DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
Jacek Caban94d95632025-02-10 21:52:11272 symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
273 symtab.localImportChunks.push_back(wrapimp->getChunk());
Martin Storsjö0b2d84f2020-11-17 14:05:29274 map[imp] = wrapimp;
275 }
276 }
Martin Storsjö3785a412020-10-06 10:54:49277 }
278
279 // Update pointers in input files.
Jacek Caban94d95632025-02-10 21:52:11280 parallelForEach(symtab.ctx.objFileInstances, [&](ObjFile *file) {
Martin Storsjö3785a412020-10-06 10:54:49281 MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
Jez Ng3df4c5a2023-01-27 01:28:58282 for (auto &sym : syms)
283 if (Symbol *s = map.lookup(sym))
284 sym = s;
Martin Storsjö3785a412020-10-06 10:54:49285 });
286}