xref: /freebsd/contrib/llvm-project/lld/COFF/MinGW.cpp (revision 85868e8a1daeaae7a0e48effb2ea2310ae3b02c6)
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;
180b57cec5SDimitry Andric 
19*85868e8aSDimitry Andric namespace lld {
20*85868e8aSDimitry Andric namespace coff {
21*85868e8aSDimitry Andric 
220b57cec5SDimitry Andric AutoExporter::AutoExporter() {
230b57cec5SDimitry Andric   excludeLibs = {
240b57cec5SDimitry Andric       "libgcc",
250b57cec5SDimitry Andric       "libgcc_s",
260b57cec5SDimitry Andric       "libstdc++",
270b57cec5SDimitry Andric       "libmingw32",
280b57cec5SDimitry Andric       "libmingwex",
290b57cec5SDimitry Andric       "libg2c",
300b57cec5SDimitry Andric       "libsupc++",
310b57cec5SDimitry Andric       "libobjc",
320b57cec5SDimitry Andric       "libgcj",
330b57cec5SDimitry Andric       "libclang_rt.builtins",
340b57cec5SDimitry Andric       "libclang_rt.builtins-aarch64",
350b57cec5SDimitry Andric       "libclang_rt.builtins-arm",
360b57cec5SDimitry Andric       "libclang_rt.builtins-i386",
370b57cec5SDimitry Andric       "libclang_rt.builtins-x86_64",
380b57cec5SDimitry Andric       "libc++",
390b57cec5SDimitry Andric       "libc++abi",
400b57cec5SDimitry Andric       "libunwind",
410b57cec5SDimitry Andric       "libmsvcrt",
420b57cec5SDimitry Andric       "libucrtbase",
430b57cec5SDimitry Andric   };
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   excludeObjects = {
460b57cec5SDimitry Andric       "crt0.o",    "crt1.o",  "crt1u.o", "crt2.o",  "crt2u.o",    "dllcrt1.o",
470b57cec5SDimitry Andric       "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
480b57cec5SDimitry Andric   };
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   excludeSymbolPrefixes = {
510b57cec5SDimitry Andric       // Import symbols
520b57cec5SDimitry Andric       "__imp_",
530b57cec5SDimitry Andric       "__IMPORT_DESCRIPTOR_",
540b57cec5SDimitry Andric       // Extra import symbols from GNU import libraries
550b57cec5SDimitry Andric       "__nm_",
560b57cec5SDimitry Andric       // C++ symbols
570b57cec5SDimitry Andric       "__rtti_",
580b57cec5SDimitry Andric       "__builtin_",
59*85868e8aSDimitry Andric       // Artificial symbols such as .refptr
600b57cec5SDimitry Andric       ".",
610b57cec5SDimitry Andric   };
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   excludeSymbolSuffixes = {
640b57cec5SDimitry Andric       "_iname",
650b57cec5SDimitry Andric       "_NULL_THUNK_DATA",
660b57cec5SDimitry Andric   };
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   if (config->machine == I386) {
690b57cec5SDimitry Andric     excludeSymbols = {
700b57cec5SDimitry Andric         "__NULL_IMPORT_DESCRIPTOR",
710b57cec5SDimitry Andric         "__pei386_runtime_relocator",
720b57cec5SDimitry Andric         "_do_pseudo_reloc",
730b57cec5SDimitry Andric         "_impure_ptr",
740b57cec5SDimitry Andric         "__impure_ptr",
750b57cec5SDimitry Andric         "__fmode",
760b57cec5SDimitry Andric         "_environ",
770b57cec5SDimitry Andric         "___dso_handle",
780b57cec5SDimitry Andric         // These are the MinGW names that differ from the standard
790b57cec5SDimitry Andric         // ones (lacking an extra underscore).
800b57cec5SDimitry Andric         "_DllMain@12",
810b57cec5SDimitry Andric         "_DllEntryPoint@12",
820b57cec5SDimitry Andric         "_DllMainCRTStartup@12",
830b57cec5SDimitry Andric     };
840b57cec5SDimitry Andric     excludeSymbolPrefixes.insert("__head_");
850b57cec5SDimitry Andric   } else {
860b57cec5SDimitry Andric     excludeSymbols = {
870b57cec5SDimitry Andric         "__NULL_IMPORT_DESCRIPTOR",
880b57cec5SDimitry Andric         "_pei386_runtime_relocator",
890b57cec5SDimitry Andric         "do_pseudo_reloc",
900b57cec5SDimitry Andric         "impure_ptr",
910b57cec5SDimitry Andric         "_impure_ptr",
920b57cec5SDimitry Andric         "_fmode",
930b57cec5SDimitry Andric         "environ",
940b57cec5SDimitry Andric         "__dso_handle",
950b57cec5SDimitry Andric         // These are the MinGW names that differ from the standard
960b57cec5SDimitry Andric         // ones (lacking an extra underscore).
970b57cec5SDimitry Andric         "DllMain",
980b57cec5SDimitry Andric         "DllEntryPoint",
990b57cec5SDimitry Andric         "DllMainCRTStartup",
1000b57cec5SDimitry Andric     };
1010b57cec5SDimitry Andric     excludeSymbolPrefixes.insert("_head_");
1020b57cec5SDimitry Andric   }
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric void AutoExporter::addWholeArchive(StringRef path) {
1060b57cec5SDimitry Andric   StringRef libName = sys::path::filename(path);
1070b57cec5SDimitry Andric   // Drop the file extension, to match the processing below.
1080b57cec5SDimitry Andric   libName = libName.substr(0, libName.rfind('.'));
1090b57cec5SDimitry Andric   excludeLibs.erase(libName);
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric bool AutoExporter::shouldExport(Defined *sym) const {
1130b57cec5SDimitry Andric   if (!sym || !sym->isLive() || !sym->getChunk())
1140b57cec5SDimitry Andric     return false;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   // Only allow the symbol kinds that make sense to export; in particular,
1170b57cec5SDimitry Andric   // disallow import symbols.
1180b57cec5SDimitry Andric   if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym))
1190b57cec5SDimitry Andric     return false;
1200b57cec5SDimitry Andric   if (excludeSymbols.count(sym->getName()))
1210b57cec5SDimitry Andric     return false;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   for (StringRef prefix : excludeSymbolPrefixes.keys())
1240b57cec5SDimitry Andric     if (sym->getName().startswith(prefix))
1250b57cec5SDimitry Andric       return false;
1260b57cec5SDimitry Andric   for (StringRef suffix : excludeSymbolSuffixes.keys())
1270b57cec5SDimitry Andric     if (sym->getName().endswith(suffix))
1280b57cec5SDimitry Andric       return false;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   // If a corresponding __imp_ symbol exists and is defined, don't export it.
1310b57cec5SDimitry Andric   if (symtab->find(("__imp_" + sym->getName()).str()))
1320b57cec5SDimitry Andric     return false;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   // Check that file is non-null before dereferencing it, symbols not
1350b57cec5SDimitry Andric   // originating in regular object files probably shouldn't be exported.
1360b57cec5SDimitry Andric   if (!sym->getFile())
1370b57cec5SDimitry Andric     return false;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   StringRef libName = sys::path::filename(sym->getFile()->parentName);
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   // Drop the file extension.
1420b57cec5SDimitry Andric   libName = libName.substr(0, libName.rfind('.'));
1430b57cec5SDimitry Andric   if (!libName.empty())
1440b57cec5SDimitry Andric     return !excludeLibs.count(libName);
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   StringRef fileName = sys::path::filename(sym->getFile()->getName());
1470b57cec5SDimitry Andric   return !excludeObjects.count(fileName);
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
150*85868e8aSDimitry Andric void writeDefFile(StringRef name) {
1510b57cec5SDimitry Andric   std::error_code ec;
152*85868e8aSDimitry Andric   raw_fd_ostream os(name, ec, sys::fs::OF_None);
1530b57cec5SDimitry Andric   if (ec)
1540b57cec5SDimitry Andric     fatal("cannot open " + name + ": " + ec.message());
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   os << "EXPORTS\n";
1570b57cec5SDimitry Andric   for (Export &e : config->exports) {
1580b57cec5SDimitry Andric     os << "    " << e.exportName << " "
1590b57cec5SDimitry Andric        << "@" << e.ordinal;
1600b57cec5SDimitry Andric     if (auto *def = dyn_cast_or_null<Defined>(e.sym)) {
1610b57cec5SDimitry Andric       if (def && def->getChunk() &&
1620b57cec5SDimitry Andric           !(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
1630b57cec5SDimitry Andric         os << " DATA";
1640b57cec5SDimitry Andric     }
1650b57cec5SDimitry Andric     os << "\n";
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric }
168*85868e8aSDimitry Andric 
169*85868e8aSDimitry Andric } // namespace coff
170*85868e8aSDimitry Andric } // namespace lld
171