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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "MinGW.h" 10 #include "SymbolTable.h" 11 #include "lld/Common/ErrorHandler.h" 12 #include "llvm/Object/COFF.h" 13 #include "llvm/Support/Path.h" 14 #include "llvm/Support/raw_ostream.h" 15 16 using namespace lld; 17 using namespace lld::coff; 18 using namespace llvm; 19 using namespace llvm::COFF; 20 21 AutoExporter::AutoExporter() { 22 excludeLibs = { 23 "libgcc", 24 "libgcc_s", 25 "libstdc++", 26 "libmingw32", 27 "libmingwex", 28 "libg2c", 29 "libsupc++", 30 "libobjc", 31 "libgcj", 32 "libclang_rt.builtins", 33 "libclang_rt.builtins-aarch64", 34 "libclang_rt.builtins-arm", 35 "libclang_rt.builtins-i386", 36 "libclang_rt.builtins-x86_64", 37 "libc++", 38 "libc++abi", 39 "libunwind", 40 "libmsvcrt", 41 "libucrtbase", 42 }; 43 44 excludeObjects = { 45 "crt0.o", "crt1.o", "crt1u.o", "crt2.o", "crt2u.o", "dllcrt1.o", 46 "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o", 47 }; 48 49 excludeSymbolPrefixes = { 50 // Import symbols 51 "__imp_", 52 "__IMPORT_DESCRIPTOR_", 53 // Extra import symbols from GNU import libraries 54 "__nm_", 55 // C++ symbols 56 "__rtti_", 57 "__builtin_", 58 // Artifical symbols such as .refptr 59 ".", 60 }; 61 62 excludeSymbolSuffixes = { 63 "_iname", 64 "_NULL_THUNK_DATA", 65 }; 66 67 if (config->machine == I386) { 68 excludeSymbols = { 69 "__NULL_IMPORT_DESCRIPTOR", 70 "__pei386_runtime_relocator", 71 "_do_pseudo_reloc", 72 "_impure_ptr", 73 "__impure_ptr", 74 "__fmode", 75 "_environ", 76 "___dso_handle", 77 // These are the MinGW names that differ from the standard 78 // ones (lacking an extra underscore). 79 "_DllMain@12", 80 "_DllEntryPoint@12", 81 "_DllMainCRTStartup@12", 82 }; 83 excludeSymbolPrefixes.insert("__head_"); 84 } else { 85 excludeSymbols = { 86 "__NULL_IMPORT_DESCRIPTOR", 87 "_pei386_runtime_relocator", 88 "do_pseudo_reloc", 89 "impure_ptr", 90 "_impure_ptr", 91 "_fmode", 92 "environ", 93 "__dso_handle", 94 // These are the MinGW names that differ from the standard 95 // ones (lacking an extra underscore). 96 "DllMain", 97 "DllEntryPoint", 98 "DllMainCRTStartup", 99 }; 100 excludeSymbolPrefixes.insert("_head_"); 101 } 102 } 103 104 void AutoExporter::addWholeArchive(StringRef path) { 105 StringRef libName = sys::path::filename(path); 106 // Drop the file extension, to match the processing below. 107 libName = libName.substr(0, libName.rfind('.')); 108 excludeLibs.erase(libName); 109 } 110 111 bool AutoExporter::shouldExport(Defined *sym) const { 112 if (!sym || !sym->isLive() || !sym->getChunk()) 113 return false; 114 115 // Only allow the symbol kinds that make sense to export; in particular, 116 // disallow import symbols. 117 if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym)) 118 return false; 119 if (excludeSymbols.count(sym->getName())) 120 return false; 121 122 for (StringRef prefix : excludeSymbolPrefixes.keys()) 123 if (sym->getName().startswith(prefix)) 124 return false; 125 for (StringRef suffix : excludeSymbolSuffixes.keys()) 126 if (sym->getName().endswith(suffix)) 127 return false; 128 129 // If a corresponding __imp_ symbol exists and is defined, don't export it. 130 if (symtab->find(("__imp_" + sym->getName()).str())) 131 return false; 132 133 // Check that file is non-null before dereferencing it, symbols not 134 // originating in regular object files probably shouldn't be exported. 135 if (!sym->getFile()) 136 return false; 137 138 StringRef libName = sys::path::filename(sym->getFile()->parentName); 139 140 // Drop the file extension. 141 libName = libName.substr(0, libName.rfind('.')); 142 if (!libName.empty()) 143 return !excludeLibs.count(libName); 144 145 StringRef fileName = sys::path::filename(sym->getFile()->getName()); 146 return !excludeObjects.count(fileName); 147 } 148 149 void coff::writeDefFile(StringRef name) { 150 std::error_code ec; 151 raw_fd_ostream os(name, ec, sys::fs::F_None); 152 if (ec) 153 fatal("cannot open " + name + ": " + ec.message()); 154 155 os << "EXPORTS\n"; 156 for (Export &e : config->exports) { 157 os << " " << e.exportName << " " 158 << "@" << e.ordinal; 159 if (auto *def = dyn_cast_or_null<Defined>(e.sym)) { 160 if (def && def->getChunk() && 161 !(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)) 162 os << " DATA"; 163 } 164 os << "\n"; 165 } 166 } 167