2017-10-19 19:49:38 +00:00
|
|
|
//===- MinGW.cpp ----------------------------------------------------------===//
|
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-10-19 19:49:38 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "MinGW.h"
|
2021-09-16 16:48:26 -07:00
|
|
|
#include "COFFLinkerContext.h"
|
2020-10-06 13:54:49 +03:00
|
|
|
#include "Driver.h"
|
|
|
|
#include "InputFiles.h"
|
2017-11-29 05:50:49 +00:00
|
|
|
#include "SymbolTable.h"
|
2020-10-06 13:54:49 +03:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2017-10-19 19:49:38 +00:00
|
|
|
#include "llvm/Object/COFF.h"
|
2020-10-06 13:54:49 +03:00
|
|
|
#include "llvm/Support/Parallel.h"
|
2017-10-19 19:49:38 +00:00
|
|
|
#include "llvm/Support/Path.h"
|
2023-10-05 22:33:58 -04:00
|
|
|
#include "llvm/Support/TimeProfiler.h"
|
2017-10-19 19:49:38 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::COFF;
|
2020-02-19 17:05:42 -08:00
|
|
|
using namespace lld;
|
|
|
|
using namespace lld::coff;
|
2019-10-10 11:27:58 +00:00
|
|
|
|
2022-07-18 00:11:37 +03:00
|
|
|
AutoExporter::AutoExporter(
|
2025-02-06 22:25:53 +01:00
|
|
|
SymbolTable &symtab, const llvm::DenseSet<StringRef> &manualExcludeSymbols)
|
|
|
|
: manualExcludeSymbols(manualExcludeSymbols), symtab(symtab) {
|
2019-07-11 05:40:30 +00:00
|
|
|
excludeLibs = {
|
2019-02-19 22:06:44 +00:00
|
|
|
"libgcc",
|
|
|
|
"libgcc_s",
|
|
|
|
"libstdc++",
|
|
|
|
"libmingw32",
|
|
|
|
"libmingwex",
|
|
|
|
"libg2c",
|
|
|
|
"libsupc++",
|
|
|
|
"libobjc",
|
|
|
|
"libgcj",
|
|
|
|
"libclang_rt.builtins",
|
|
|
|
"libclang_rt.builtins-aarch64",
|
|
|
|
"libclang_rt.builtins-arm",
|
|
|
|
"libclang_rt.builtins-i386",
|
|
|
|
"libclang_rt.builtins-x86_64",
|
2020-07-30 23:32:37 +03:00
|
|
|
"libclang_rt.profile",
|
|
|
|
"libclang_rt.profile-aarch64",
|
|
|
|
"libclang_rt.profile-arm",
|
|
|
|
"libclang_rt.profile-i386",
|
|
|
|
"libclang_rt.profile-x86_64",
|
2019-02-19 22:06:44 +00:00
|
|
|
"libc++",
|
|
|
|
"libc++abi",
|
2025-02-08 18:02:54 +01:00
|
|
|
"libflang_rt.runtime",
|
2019-02-19 22:06:44 +00:00
|
|
|
"libunwind",
|
|
|
|
"libmsvcrt",
|
2025-03-21 15:33:25 +02:00
|
|
|
"libmsvcrt-os",
|
2019-02-19 22:06:44 +00:00
|
|
|
"libucrtbase",
|
2025-03-21 15:33:25 +02:00
|
|
|
"libucrt",
|
|
|
|
"libucrtapp",
|
|
|
|
"libpthread",
|
|
|
|
"libwinpthread",
|
2019-02-19 22:06:44 +00:00
|
|
|
};
|
|
|
|
|
2019-07-11 05:40:30 +00:00
|
|
|
excludeObjects = {
|
2019-02-19 22:06:44 +00:00
|
|
|
"crt0.o", "crt1.o", "crt1u.o", "crt2.o", "crt2u.o", "dllcrt1.o",
|
|
|
|
"dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
|
|
|
|
};
|
|
|
|
|
2019-07-11 05:40:30 +00:00
|
|
|
excludeSymbolPrefixes = {
|
2018-09-26 06:13:47 +00:00
|
|
|
// Import symbols
|
|
|
|
"__imp_",
|
|
|
|
"__IMPORT_DESCRIPTOR_",
|
|
|
|
// Extra import symbols from GNU import libraries
|
|
|
|
"__nm_",
|
|
|
|
// C++ symbols
|
|
|
|
"__rtti_",
|
|
|
|
"__builtin_",
|
2019-10-10 02:04:56 +00:00
|
|
|
// Artificial symbols such as .refptr
|
2018-09-26 06:13:47 +00:00
|
|
|
".",
|
2020-07-30 23:32:37 +03:00
|
|
|
// profile generate symbols
|
|
|
|
"__profc_",
|
|
|
|
"__profd_",
|
|
|
|
"__profvp_",
|
2018-09-26 06:13:47 +00:00
|
|
|
};
|
2019-02-19 22:06:44 +00:00
|
|
|
|
2019-07-11 05:40:30 +00:00
|
|
|
excludeSymbolSuffixes = {
|
2018-09-26 06:13:47 +00:00
|
|
|
"_iname",
|
|
|
|
"_NULL_THUNK_DATA",
|
|
|
|
};
|
2019-02-19 22:06:44 +00:00
|
|
|
|
2025-02-06 22:25:53 +01:00
|
|
|
if (symtab.machine == I386) {
|
2019-07-11 05:40:30 +00:00
|
|
|
excludeSymbols = {
|
2017-10-19 19:49:38 +00:00
|
|
|
"__NULL_IMPORT_DESCRIPTOR",
|
|
|
|
"__pei386_runtime_relocator",
|
|
|
|
"_do_pseudo_reloc",
|
|
|
|
"_impure_ptr",
|
|
|
|
"__impure_ptr",
|
|
|
|
"__fmode",
|
|
|
|
"_environ",
|
|
|
|
"___dso_handle",
|
2025-02-07 15:52:39 +01:00
|
|
|
"__load_config_used",
|
2017-10-19 19:49:38 +00:00
|
|
|
// These are the MinGW names that differ from the standard
|
|
|
|
// ones (lacking an extra underscore).
|
|
|
|
"_DllMain@12",
|
|
|
|
"_DllEntryPoint@12",
|
|
|
|
"_DllMainCRTStartup@12",
|
|
|
|
};
|
2019-07-11 05:40:30 +00:00
|
|
|
excludeSymbolPrefixes.insert("__head_");
|
2017-11-22 09:06:27 +00:00
|
|
|
} else {
|
2019-07-11 05:40:30 +00:00
|
|
|
excludeSymbols = {
|
2018-09-18 07:22:05 +00:00
|
|
|
"__NULL_IMPORT_DESCRIPTOR",
|
2017-10-19 19:49:38 +00:00
|
|
|
"_pei386_runtime_relocator",
|
|
|
|
"do_pseudo_reloc",
|
|
|
|
"impure_ptr",
|
|
|
|
"_impure_ptr",
|
|
|
|
"_fmode",
|
|
|
|
"environ",
|
|
|
|
"__dso_handle",
|
2025-02-07 15:52:39 +01:00
|
|
|
"_load_config_used",
|
2017-10-19 19:49:38 +00:00
|
|
|
// These are the MinGW names that differ from the standard
|
|
|
|
// ones (lacking an extra underscore).
|
|
|
|
"DllMain",
|
|
|
|
"DllEntryPoint",
|
|
|
|
"DllMainCRTStartup",
|
|
|
|
};
|
2019-07-11 05:40:30 +00:00
|
|
|
excludeSymbolPrefixes.insert("_head_");
|
2017-11-22 09:06:27 +00:00
|
|
|
}
|
2025-02-07 15:52:39 +01:00
|
|
|
if (symtab.isEC()) {
|
|
|
|
excludeSymbols.insert("__chpe_metadata");
|
|
|
|
excludeSymbolPrefixes.insert("__os_arm64x_");
|
|
|
|
}
|
2018-09-04 20:56:56 +00:00
|
|
|
}
|
2017-10-19 19:49:38 +00:00
|
|
|
|
2019-07-11 05:40:30 +00:00
|
|
|
void AutoExporter::addWholeArchive(StringRef path) {
|
|
|
|
StringRef libName = sys::path::filename(path);
|
2018-09-04 20:56:56 +00:00
|
|
|
// Drop the file extension, to match the processing below.
|
2019-07-11 05:40:30 +00:00
|
|
|
libName = libName.substr(0, libName.rfind('.'));
|
|
|
|
excludeLibs.erase(libName);
|
2018-09-04 20:56:56 +00:00
|
|
|
}
|
|
|
|
|
2022-07-18 23:43:02 +03:00
|
|
|
void AutoExporter::addExcludedSymbol(StringRef symbol) {
|
|
|
|
excludeSymbols.insert(symbol);
|
|
|
|
}
|
|
|
|
|
2023-01-09 23:37:28 -05:00
|
|
|
bool AutoExporter::shouldExport(Defined *sym) const {
|
2021-04-29 11:57:33 +03:00
|
|
|
if (!sym || !sym->getChunk())
|
2017-10-19 19:49:38 +00:00
|
|
|
return false;
|
2017-11-22 09:06:27 +00:00
|
|
|
|
2017-11-16 07:22:44 +00:00
|
|
|
// Only allow the symbol kinds that make sense to export; in particular,
|
|
|
|
// disallow import symbols.
|
2019-07-11 05:40:30 +00:00
|
|
|
if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym))
|
2017-11-16 07:22:44 +00:00
|
|
|
return false;
|
2022-07-18 00:11:37 +03:00
|
|
|
if (excludeSymbols.count(sym->getName()) || manualExcludeSymbols.count(sym->getName()))
|
2017-10-19 19:49:38 +00:00
|
|
|
return false;
|
2017-11-22 09:06:27 +00:00
|
|
|
|
2019-07-11 05:40:30 +00:00
|
|
|
for (StringRef prefix : excludeSymbolPrefixes.keys())
|
2023-06-05 14:36:19 -07:00
|
|
|
if (sym->getName().starts_with(prefix))
|
2018-09-26 06:13:47 +00:00
|
|
|
return false;
|
2019-07-11 05:40:30 +00:00
|
|
|
for (StringRef suffix : excludeSymbolSuffixes.keys())
|
2023-06-05 14:36:19 -07:00
|
|
|
if (sym->getName().ends_with(suffix))
|
2018-09-26 06:13:47 +00:00
|
|
|
return false;
|
2017-11-29 05:50:49 +00:00
|
|
|
|
|
|
|
// If a corresponding __imp_ symbol exists and is defined, don't export it.
|
2025-02-06 22:25:53 +01:00
|
|
|
if (symtab.find(("__imp_" + sym->getName()).str()))
|
2017-11-29 05:50:49 +00:00
|
|
|
return false;
|
|
|
|
|
2017-11-16 07:22:44 +00:00
|
|
|
// Check that file is non-null before dereferencing it, symbols not
|
|
|
|
// originating in regular object files probably shouldn't be exported.
|
2019-07-11 05:40:30 +00:00
|
|
|
if (!sym->getFile())
|
2017-11-16 07:22:44 +00:00
|
|
|
return false;
|
2017-11-22 09:06:27 +00:00
|
|
|
|
2019-07-11 05:40:30 +00:00
|
|
|
StringRef libName = sys::path::filename(sym->getFile()->parentName);
|
2017-11-22 09:06:27 +00:00
|
|
|
|
2017-10-19 19:49:38 +00:00
|
|
|
// Drop the file extension.
|
2019-07-11 05:40:30 +00:00
|
|
|
libName = libName.substr(0, libName.rfind('.'));
|
|
|
|
if (!libName.empty())
|
|
|
|
return !excludeLibs.count(libName);
|
2017-11-22 09:06:27 +00:00
|
|
|
|
2019-07-11 05:40:30 +00:00
|
|
|
StringRef fileName = sys::path::filename(sym->getFile()->getName());
|
|
|
|
return !excludeObjects.count(fileName);
|
2017-10-19 19:49:38 +00:00
|
|
|
}
|
|
|
|
|
2024-12-05 20:41:36 -08:00
|
|
|
void lld::coff::writeDefFile(COFFLinkerContext &ctx, StringRef name,
|
2023-01-09 23:37:28 -05:00
|
|
|
const std::vector<Export> &exports) {
|
2023-10-05 22:33:58 -04:00
|
|
|
llvm::TimeTraceScope timeScope("Write .def file");
|
2019-07-11 05:40:30 +00:00
|
|
|
std::error_code ec;
|
2019-08-05 05:43:48 +00:00
|
|
|
raw_fd_ostream os(name, ec, sys::fs::OF_None);
|
2019-07-11 05:40:30 +00:00
|
|
|
if (ec)
|
2024-12-05 20:41:36 -08:00
|
|
|
Fatal(ctx) << "cannot open " << name << ": " << ec.message();
|
2019-07-11 05:40:30 +00:00
|
|
|
|
|
|
|
os << "EXPORTS\n";
|
2023-01-09 23:37:28 -05:00
|
|
|
for (const Export &e : exports) {
|
2019-07-11 05:40:30 +00:00
|
|
|
os << " " << e.exportName << " "
|
|
|
|
<< "@" << e.ordinal;
|
|
|
|
if (auto *def = dyn_cast_or_null<Defined>(e.sym)) {
|
|
|
|
if (def && def->getChunk() &&
|
|
|
|
!(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
|
|
|
|
os << " DATA";
|
2017-10-19 19:49:38 +00:00
|
|
|
}
|
2019-07-11 05:40:30 +00:00
|
|
|
os << "\n";
|
2017-10-19 19:49:38 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-06 13:54:49 +03:00
|
|
|
|
2023-01-09 23:37:28 -05:00
|
|
|
static StringRef mangle(Twine sym, MachineTypes machine) {
|
|
|
|
assert(machine != IMAGE_FILE_MACHINE_UNKNOWN);
|
|
|
|
if (machine == I386)
|
2022-01-20 14:53:18 -05:00
|
|
|
return saver().save("_" + sym);
|
|
|
|
return saver().save(sym);
|
2020-10-06 13:54:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handles -wrap option.
|
|
|
|
//
|
|
|
|
// This function instantiates wrapper symbols. At this point, they seem
|
|
|
|
// like they are not being used at all, so we explicitly set some flags so
|
|
|
|
// that LTO won't eliminate them.
|
2025-02-10 22:52:11 +01:00
|
|
|
void lld::coff::addWrappedSymbols(SymbolTable &symtab,
|
|
|
|
opt::InputArgList &args) {
|
2020-10-06 13:54:49 +03:00
|
|
|
std::vector<WrappedSymbol> v;
|
|
|
|
DenseSet<StringRef> seen;
|
|
|
|
|
|
|
|
for (auto *arg : args.filtered(OPT_wrap)) {
|
|
|
|
StringRef name = arg->getValue();
|
|
|
|
if (!seen.insert(name).second)
|
|
|
|
continue;
|
|
|
|
|
2025-02-10 22:52:11 +01:00
|
|
|
Symbol *sym = symtab.findUnderscore(name);
|
2020-10-06 13:54:49 +03:00
|
|
|
if (!sym)
|
|
|
|
continue;
|
|
|
|
|
2023-01-09 23:37:28 -05:00
|
|
|
Symbol *real =
|
2025-02-10 22:52:11 +01:00
|
|
|
symtab.addUndefined(mangle("__real_" + name, symtab.machine));
|
2023-01-09 23:37:28 -05:00
|
|
|
Symbol *wrap =
|
2025-02-10 22:52:11 +01:00
|
|
|
symtab.addUndefined(mangle("__wrap_" + name, symtab.machine));
|
2020-10-06 13:54:49 +03:00
|
|
|
v.push_back({sym, real, wrap});
|
|
|
|
|
|
|
|
// These symbols may seem undefined initially, but don't bail out
|
2021-09-16 16:48:26 -07:00
|
|
|
// at symtab.reportUnresolvable() due to them, but let wrapSymbols
|
2020-10-06 13:54:49 +03:00
|
|
|
// below sort things out before checking finally with
|
2021-09-16 16:48:26 -07:00
|
|
|
// symtab.resolveRemainingUndefines().
|
2020-10-06 13:54:49 +03:00
|
|
|
sym->deferUndefined = true;
|
|
|
|
real->deferUndefined = true;
|
|
|
|
// We want to tell LTO not to inline symbols to be overwritten
|
|
|
|
// because LTO doesn't know the final symbol contents after renaming.
|
|
|
|
real->canInline = false;
|
|
|
|
sym->canInline = false;
|
|
|
|
|
|
|
|
// Tell LTO not to eliminate these symbols.
|
|
|
|
sym->isUsedInRegularObj = true;
|
|
|
|
if (!isa<Undefined>(wrap))
|
|
|
|
wrap->isUsedInRegularObj = true;
|
|
|
|
}
|
2025-02-10 22:52:11 +01:00
|
|
|
symtab.wrapped = std::move(v);
|
2020-10-06 13:54:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do renaming for -wrap by updating pointers to symbols.
|
|
|
|
//
|
|
|
|
// When this function is executed, only InputFiles and symbol table
|
|
|
|
// contain pointers to symbol objects. We visit them to replace pointers,
|
|
|
|
// so that wrapped symbols are swapped as instructed by the command line.
|
2025-02-10 22:52:11 +01:00
|
|
|
void lld::coff::wrapSymbols(SymbolTable &symtab) {
|
2020-10-06 13:54:49 +03:00
|
|
|
DenseMap<Symbol *, Symbol *> map;
|
2025-02-10 22:52:11 +01:00
|
|
|
for (const WrappedSymbol &w : symtab.wrapped) {
|
2020-10-06 13:54:49 +03:00
|
|
|
map[w.sym] = w.wrap;
|
|
|
|
map[w.real] = w.sym;
|
2020-11-17 16:05:29 +02:00
|
|
|
if (Defined *d = dyn_cast<Defined>(w.wrap)) {
|
2025-02-10 22:52:11 +01:00
|
|
|
Symbol *imp = symtab.find(("__imp_" + w.sym->getName()).str());
|
2020-11-17 16:05:29 +02:00
|
|
|
// Create a new defined local import for the wrap symbol. If
|
|
|
|
// no imp prefixed symbol existed, there's no need for it.
|
|
|
|
// (We can't easily distinguish whether any object file actually
|
|
|
|
// referenced it or not, though.)
|
|
|
|
if (imp) {
|
|
|
|
DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
|
2025-02-10 22:52:11 +01:00
|
|
|
symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
|
|
|
|
symtab.localImportChunks.push_back(wrapimp->getChunk());
|
2020-11-17 16:05:29 +02:00
|
|
|
map[imp] = wrapimp;
|
|
|
|
}
|
|
|
|
}
|
2020-10-06 13:54:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update pointers in input files.
|
2025-02-10 22:52:11 +01:00
|
|
|
parallelForEach(symtab.ctx.objFileInstances, [&](ObjFile *file) {
|
2020-10-06 13:54:49 +03:00
|
|
|
MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
|
2023-01-26 20:28:58 -05:00
|
|
|
for (auto &sym : syms)
|
|
|
|
if (Symbol *s = map.lookup(sym))
|
|
|
|
sym = s;
|
2020-10-06 13:54:49 +03:00
|
|
|
});
|
|
|
|
}
|