Path: blob/main/contrib/llvm-project/lld/COFF/MinGW.cpp
34870 views
//===- MinGW.cpp ----------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MinGW.h"9#include "COFFLinkerContext.h"10#include "Driver.h"11#include "InputFiles.h"12#include "SymbolTable.h"13#include "llvm/ADT/DenseMap.h"14#include "llvm/ADT/DenseSet.h"15#include "llvm/Object/COFF.h"16#include "llvm/Support/Parallel.h"17#include "llvm/Support/Path.h"18#include "llvm/Support/TimeProfiler.h"19#include "llvm/Support/raw_ostream.h"2021using namespace llvm;22using namespace llvm::COFF;23using namespace lld;24using namespace lld::coff;2526AutoExporter::AutoExporter(27COFFLinkerContext &ctx,28const llvm::DenseSet<StringRef> &manualExcludeSymbols)29: manualExcludeSymbols(manualExcludeSymbols), ctx(ctx) {30excludeLibs = {31"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",45"libclang_rt.profile",46"libclang_rt.profile-aarch64",47"libclang_rt.profile-arm",48"libclang_rt.profile-i386",49"libclang_rt.profile-x86_64",50"libc++",51"libc++abi",52"libFortranRuntime",53"libFortranDecimal",54"libunwind",55"libmsvcrt",56"libucrtbase",57};5859excludeObjects = {60"crt0.o", "crt1.o", "crt1u.o", "crt2.o", "crt2u.o", "dllcrt1.o",61"dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",62};6364excludeSymbolPrefixes = {65// Import symbols66"__imp_",67"__IMPORT_DESCRIPTOR_",68// Extra import symbols from GNU import libraries69"__nm_",70// C++ symbols71"__rtti_",72"__builtin_",73// Artificial symbols such as .refptr74".",75// profile generate symbols76"__profc_",77"__profd_",78"__profvp_",79};8081excludeSymbolSuffixes = {82"_iname",83"_NULL_THUNK_DATA",84};8586if (ctx.config.machine == I386) {87excludeSymbols = {88"__NULL_IMPORT_DESCRIPTOR",89"__pei386_runtime_relocator",90"_do_pseudo_reloc",91"_impure_ptr",92"__impure_ptr",93"__fmode",94"_environ",95"___dso_handle",96// These are the MinGW names that differ from the standard97// ones (lacking an extra underscore).98"_DllMain@12",99"_DllEntryPoint@12",100"_DllMainCRTStartup@12",101};102excludeSymbolPrefixes.insert("__head_");103} else {104excludeSymbols = {105"__NULL_IMPORT_DESCRIPTOR",106"_pei386_runtime_relocator",107"do_pseudo_reloc",108"impure_ptr",109"_impure_ptr",110"_fmode",111"environ",112"__dso_handle",113// These are the MinGW names that differ from the standard114// ones (lacking an extra underscore).115"DllMain",116"DllEntryPoint",117"DllMainCRTStartup",118};119excludeSymbolPrefixes.insert("_head_");120}121}122123void AutoExporter::addWholeArchive(StringRef path) {124StringRef libName = sys::path::filename(path);125// Drop the file extension, to match the processing below.126libName = libName.substr(0, libName.rfind('.'));127excludeLibs.erase(libName);128}129130void AutoExporter::addExcludedSymbol(StringRef symbol) {131excludeSymbols.insert(symbol);132}133134bool AutoExporter::shouldExport(Defined *sym) const {135if (!sym || !sym->getChunk())136return false;137138// Only allow the symbol kinds that make sense to export; in particular,139// disallow import symbols.140if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym))141return false;142if (excludeSymbols.count(sym->getName()) || manualExcludeSymbols.count(sym->getName()))143return false;144145for (StringRef prefix : excludeSymbolPrefixes.keys())146if (sym->getName().starts_with(prefix))147return false;148for (StringRef suffix : excludeSymbolSuffixes.keys())149if (sym->getName().ends_with(suffix))150return false;151152// If a corresponding __imp_ symbol exists and is defined, don't export it.153if (ctx.symtab.find(("__imp_" + sym->getName()).str()))154return false;155156// Check that file is non-null before dereferencing it, symbols not157// originating in regular object files probably shouldn't be exported.158if (!sym->getFile())159return false;160161StringRef libName = sys::path::filename(sym->getFile()->parentName);162163// Drop the file extension.164libName = libName.substr(0, libName.rfind('.'));165if (!libName.empty())166return !excludeLibs.count(libName);167168StringRef fileName = sys::path::filename(sym->getFile()->getName());169return !excludeObjects.count(fileName);170}171172void lld::coff::writeDefFile(StringRef name,173const std::vector<Export> &exports) {174llvm::TimeTraceScope timeScope("Write .def file");175std::error_code ec;176raw_fd_ostream os(name, ec, sys::fs::OF_None);177if (ec)178fatal("cannot open " + name + ": " + ec.message());179180os << "EXPORTS\n";181for (const Export &e : exports) {182os << " " << e.exportName << " "183<< "@" << e.ordinal;184if (auto *def = dyn_cast_or_null<Defined>(e.sym)) {185if (def && def->getChunk() &&186!(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))187os << " DATA";188}189os << "\n";190}191}192193static StringRef mangle(Twine sym, MachineTypes machine) {194assert(machine != IMAGE_FILE_MACHINE_UNKNOWN);195if (machine == I386)196return saver().save("_" + sym);197return saver().save(sym);198}199200// Handles -wrap option.201//202// This function instantiates wrapper symbols. At this point, they seem203// like they are not being used at all, so we explicitly set some flags so204// that LTO won't eliminate them.205std::vector<WrappedSymbol>206lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {207std::vector<WrappedSymbol> v;208DenseSet<StringRef> seen;209210for (auto *arg : args.filtered(OPT_wrap)) {211StringRef name = arg->getValue();212if (!seen.insert(name).second)213continue;214215Symbol *sym = ctx.symtab.findUnderscore(name);216if (!sym)217continue;218219Symbol *real =220ctx.symtab.addUndefined(mangle("__real_" + name, ctx.config.machine));221Symbol *wrap =222ctx.symtab.addUndefined(mangle("__wrap_" + name, ctx.config.machine));223v.push_back({sym, real, wrap});224225// These symbols may seem undefined initially, but don't bail out226// at symtab.reportUnresolvable() due to them, but let wrapSymbols227// below sort things out before checking finally with228// symtab.resolveRemainingUndefines().229sym->deferUndefined = true;230real->deferUndefined = true;231// We want to tell LTO not to inline symbols to be overwritten232// because LTO doesn't know the final symbol contents after renaming.233real->canInline = false;234sym->canInline = false;235236// Tell LTO not to eliminate these symbols.237sym->isUsedInRegularObj = true;238if (!isa<Undefined>(wrap))239wrap->isUsedInRegularObj = true;240}241return v;242}243244// Do renaming for -wrap by updating pointers to symbols.245//246// When this function is executed, only InputFiles and symbol table247// contain pointers to symbol objects. We visit them to replace pointers,248// so that wrapped symbols are swapped as instructed by the command line.249void lld::coff::wrapSymbols(COFFLinkerContext &ctx,250ArrayRef<WrappedSymbol> wrapped) {251DenseMap<Symbol *, Symbol *> map;252for (const WrappedSymbol &w : wrapped) {253map[w.sym] = w.wrap;254map[w.real] = w.sym;255if (Defined *d = dyn_cast<Defined>(w.wrap)) {256Symbol *imp = ctx.symtab.find(("__imp_" + w.sym->getName()).str());257// Create a new defined local import for the wrap symbol. If258// no imp prefixed symbol existed, there's no need for it.259// (We can't easily distinguish whether any object file actually260// referenced it or not, though.)261if (imp) {262DefinedLocalImport *wrapimp = make<DefinedLocalImport>(263ctx, saver().save("__imp_" + w.wrap->getName()), d);264ctx.symtab.localImportChunks.push_back(wrapimp->getChunk());265map[imp] = wrapimp;266}267}268}269270// Update pointers in input files.271parallelForEach(ctx.objFileInstances, [&](ObjFile *file) {272MutableArrayRef<Symbol *> syms = file->getMutableSymbols();273for (auto &sym : syms)274if (Symbol *s = map.lookup(sym))275sym = s;276});277}278279280