brintos

brintos / llvm-project-archived public Read only

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