xref: /freebsd/contrib/llvm-project/lld/COFF/MinGW.cpp (revision 979e22ff1ac2a50acbf94e28576a058db89003b5)
10b57cec5SDimitry Andric //===- MinGW.cpp ----------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MinGW.h"
100b57cec5SDimitry Andric #include "SymbolTable.h"
110b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h"
120b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
130b57cec5SDimitry Andric #include "llvm/Support/Path.h"
140b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric using namespace llvm;
170b57cec5SDimitry Andric using namespace llvm::COFF;
185ffd83dbSDimitry Andric using namespace lld;
195ffd83dbSDimitry Andric using namespace lld::coff;
2085868e8aSDimitry Andric 
210b57cec5SDimitry Andric AutoExporter::AutoExporter() {
220b57cec5SDimitry Andric   excludeLibs = {
230b57cec5SDimitry Andric       "libgcc",
240b57cec5SDimitry Andric       "libgcc_s",
250b57cec5SDimitry Andric       "libstdc++",
260b57cec5SDimitry Andric       "libmingw32",
270b57cec5SDimitry Andric       "libmingwex",
280b57cec5SDimitry Andric       "libg2c",
290b57cec5SDimitry Andric       "libsupc++",
300b57cec5SDimitry Andric       "libobjc",
310b57cec5SDimitry Andric       "libgcj",
320b57cec5SDimitry Andric       "libclang_rt.builtins",
330b57cec5SDimitry Andric       "libclang_rt.builtins-aarch64",
340b57cec5SDimitry Andric       "libclang_rt.builtins-arm",
350b57cec5SDimitry Andric       "libclang_rt.builtins-i386",
360b57cec5SDimitry Andric       "libclang_rt.builtins-x86_64",
37*979e22ffSDimitry Andric       "libclang_rt.profile",
38*979e22ffSDimitry Andric       "libclang_rt.profile-aarch64",
39*979e22ffSDimitry Andric       "libclang_rt.profile-arm",
40*979e22ffSDimitry Andric       "libclang_rt.profile-i386",
41*979e22ffSDimitry Andric       "libclang_rt.profile-x86_64",
420b57cec5SDimitry Andric       "libc++",
430b57cec5SDimitry Andric       "libc++abi",
440b57cec5SDimitry Andric       "libunwind",
450b57cec5SDimitry Andric       "libmsvcrt",
460b57cec5SDimitry Andric       "libucrtbase",
470b57cec5SDimitry Andric   };
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   excludeObjects = {
500b57cec5SDimitry Andric       "crt0.o",    "crt1.o",  "crt1u.o", "crt2.o",  "crt2u.o",    "dllcrt1.o",
510b57cec5SDimitry Andric       "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
520b57cec5SDimitry Andric   };
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   excludeSymbolPrefixes = {
550b57cec5SDimitry Andric       // Import symbols
560b57cec5SDimitry Andric       "__imp_",
570b57cec5SDimitry Andric       "__IMPORT_DESCRIPTOR_",
580b57cec5SDimitry Andric       // Extra import symbols from GNU import libraries
590b57cec5SDimitry Andric       "__nm_",
600b57cec5SDimitry Andric       // C++ symbols
610b57cec5SDimitry Andric       "__rtti_",
620b57cec5SDimitry Andric       "__builtin_",
6385868e8aSDimitry Andric       // Artificial symbols such as .refptr
640b57cec5SDimitry Andric       ".",
65*979e22ffSDimitry Andric       // profile generate symbols
66*979e22ffSDimitry Andric       "__profc_",
67*979e22ffSDimitry Andric       "__profd_",
68*979e22ffSDimitry Andric       "__profvp_",
690b57cec5SDimitry Andric   };
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   excludeSymbolSuffixes = {
720b57cec5SDimitry Andric       "_iname",
730b57cec5SDimitry Andric       "_NULL_THUNK_DATA",
740b57cec5SDimitry Andric   };
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   if (config->machine == I386) {
770b57cec5SDimitry Andric     excludeSymbols = {
780b57cec5SDimitry Andric         "__NULL_IMPORT_DESCRIPTOR",
790b57cec5SDimitry Andric         "__pei386_runtime_relocator",
800b57cec5SDimitry Andric         "_do_pseudo_reloc",
810b57cec5SDimitry Andric         "_impure_ptr",
820b57cec5SDimitry Andric         "__impure_ptr",
830b57cec5SDimitry Andric         "__fmode",
840b57cec5SDimitry Andric         "_environ",
850b57cec5SDimitry Andric         "___dso_handle",
860b57cec5SDimitry Andric         // These are the MinGW names that differ from the standard
870b57cec5SDimitry Andric         // ones (lacking an extra underscore).
880b57cec5SDimitry Andric         "_DllMain@12",
890b57cec5SDimitry Andric         "_DllEntryPoint@12",
900b57cec5SDimitry Andric         "_DllMainCRTStartup@12",
910b57cec5SDimitry Andric     };
920b57cec5SDimitry Andric     excludeSymbolPrefixes.insert("__head_");
930b57cec5SDimitry Andric   } else {
940b57cec5SDimitry Andric     excludeSymbols = {
950b57cec5SDimitry Andric         "__NULL_IMPORT_DESCRIPTOR",
960b57cec5SDimitry Andric         "_pei386_runtime_relocator",
970b57cec5SDimitry Andric         "do_pseudo_reloc",
980b57cec5SDimitry Andric         "impure_ptr",
990b57cec5SDimitry Andric         "_impure_ptr",
1000b57cec5SDimitry Andric         "_fmode",
1010b57cec5SDimitry Andric         "environ",
1020b57cec5SDimitry Andric         "__dso_handle",
1030b57cec5SDimitry Andric         // These are the MinGW names that differ from the standard
1040b57cec5SDimitry Andric         // ones (lacking an extra underscore).
1050b57cec5SDimitry Andric         "DllMain",
1060b57cec5SDimitry Andric         "DllEntryPoint",
1070b57cec5SDimitry Andric         "DllMainCRTStartup",
1080b57cec5SDimitry Andric     };
1090b57cec5SDimitry Andric     excludeSymbolPrefixes.insert("_head_");
1100b57cec5SDimitry Andric   }
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric void AutoExporter::addWholeArchive(StringRef path) {
1140b57cec5SDimitry Andric   StringRef libName = sys::path::filename(path);
1150b57cec5SDimitry Andric   // Drop the file extension, to match the processing below.
1160b57cec5SDimitry Andric   libName = libName.substr(0, libName.rfind('.'));
1170b57cec5SDimitry Andric   excludeLibs.erase(libName);
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric bool AutoExporter::shouldExport(Defined *sym) const {
1210b57cec5SDimitry Andric   if (!sym || !sym->isLive() || !sym->getChunk())
1220b57cec5SDimitry Andric     return false;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   // Only allow the symbol kinds that make sense to export; in particular,
1250b57cec5SDimitry Andric   // disallow import symbols.
1260b57cec5SDimitry Andric   if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym))
1270b57cec5SDimitry Andric     return false;
1280b57cec5SDimitry Andric   if (excludeSymbols.count(sym->getName()))
1290b57cec5SDimitry Andric     return false;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   for (StringRef prefix : excludeSymbolPrefixes.keys())
1320b57cec5SDimitry Andric     if (sym->getName().startswith(prefix))
1330b57cec5SDimitry Andric       return false;
1340b57cec5SDimitry Andric   for (StringRef suffix : excludeSymbolSuffixes.keys())
1350b57cec5SDimitry Andric     if (sym->getName().endswith(suffix))
1360b57cec5SDimitry Andric       return false;
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   // If a corresponding __imp_ symbol exists and is defined, don't export it.
1390b57cec5SDimitry Andric   if (symtab->find(("__imp_" + sym->getName()).str()))
1400b57cec5SDimitry Andric     return false;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   // Check that file is non-null before dereferencing it, symbols not
1430b57cec5SDimitry Andric   // originating in regular object files probably shouldn't be exported.
1440b57cec5SDimitry Andric   if (!sym->getFile())
1450b57cec5SDimitry Andric     return false;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   StringRef libName = sys::path::filename(sym->getFile()->parentName);
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   // Drop the file extension.
1500b57cec5SDimitry Andric   libName = libName.substr(0, libName.rfind('.'));
1510b57cec5SDimitry Andric   if (!libName.empty())
1520b57cec5SDimitry Andric     return !excludeLibs.count(libName);
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   StringRef fileName = sys::path::filename(sym->getFile()->getName());
1550b57cec5SDimitry Andric   return !excludeObjects.count(fileName);
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1585ffd83dbSDimitry Andric void lld::coff::writeDefFile(StringRef name) {
1590b57cec5SDimitry Andric   std::error_code ec;
16085868e8aSDimitry Andric   raw_fd_ostream os(name, ec, sys::fs::OF_None);
1610b57cec5SDimitry Andric   if (ec)
1620b57cec5SDimitry Andric     fatal("cannot open " + name + ": " + ec.message());
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   os << "EXPORTS\n";
1650b57cec5SDimitry Andric   for (Export &e : config->exports) {
1660b57cec5SDimitry Andric     os << "    " << e.exportName << " "
1670b57cec5SDimitry Andric        << "@" << e.ordinal;
1680b57cec5SDimitry Andric     if (auto *def = dyn_cast_or_null<Defined>(e.sym)) {
1690b57cec5SDimitry Andric       if (def && def->getChunk() &&
1700b57cec5SDimitry Andric           !(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
1710b57cec5SDimitry Andric         os << " DATA";
1720b57cec5SDimitry Andric     }
1730b57cec5SDimitry Andric     os << "\n";
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric }
176