1 //===- MinGW/Driver.cpp ---------------------------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // MinGW is a GNU development environment for Windows. It consists of GNU 11 // tools such as GCC and GNU ld. Unlike Cygwin, there's no POSIX-compatible 12 // layer, as it aims to be a native development toolchain. 13 // 14 // lld/MinGW is a drop-in replacement for GNU ld/MinGW. 15 // 16 // Being a native development tool, a MinGW linker is not very different from 17 // Microsoft link.exe, so a MinGW linker can be implemented as a thin wrapper 18 // for lld/COFF. This driver takes Unix-ish command line options, translates 19 // them to Windows-ish ones, and then passes them to lld/COFF. 20 // 21 // When this driver calls the lld/COFF driver, it passes a hidden option 22 // "-lldmingw" along with other user-supplied options, to run the lld/COFF 23 // linker in "MinGW mode". 24 // 25 // There are subtle differences between MS link.exe and GNU ld/MinGW, and GNU 26 // ld/MinGW implements a few GNU-specific features. Such features are directly 27 // implemented in lld/COFF and enabled only when the linker is running in MinGW 28 // mode. 29 // 30 //===----------------------------------------------------------------------===// 31 32 #include "lld/Common/Driver.h" 33 #include "lld/Common/ErrorHandler.h" 34 #include "llvm/ADT/ArrayRef.h" 35 #include "llvm/ADT/Optional.h" 36 #include "llvm/ADT/StringExtras.h" 37 #include "llvm/ADT/StringRef.h" 38 #include "llvm/Option/Arg.h" 39 #include "llvm/Option/ArgList.h" 40 #include "llvm/Option/Option.h" 41 #include "llvm/Support/CommandLine.h" 42 #include "llvm/Support/FileSystem.h" 43 #include "llvm/Support/Path.h" 44 45 #if !defined(_MSC_VER) && !defined(__MINGW32__) 46 #include <unistd.h> 47 #endif 48 49 using namespace lld; 50 using namespace llvm; 51 52 // Create OptTable 53 enum { 54 OPT_INVALID = 0, 55 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, 56 #include "Options.inc" 57 #undef OPTION 58 }; 59 60 // Create prefix string literals used in Options.td 61 #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; 62 #include "Options.inc" 63 #undef PREFIX 64 65 // Create table mapping all options defined in Options.td 66 static const opt::OptTable::Info InfoTable[] = { 67 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 68 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ 69 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 70 #include "Options.inc" 71 #undef OPTION 72 }; 73 74 namespace { 75 class MinGWOptTable : public opt::OptTable { 76 public: 77 MinGWOptTable() : OptTable(InfoTable, false) {} 78 opt::InputArgList parse(ArrayRef<const char *> Argv); 79 }; 80 } // namespace 81 82 opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> Argv) { 83 unsigned MissingIndex; 84 unsigned MissingCount; 85 86 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); 87 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); 88 89 if (MissingCount) 90 fatal(StringRef(Args.getArgString(MissingIndex)) + ": missing argument"); 91 for (auto *Arg : Args.filtered(OPT_UNKNOWN)) 92 fatal("unknown argument: " + Arg->getSpelling()); 93 if (!Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l)) 94 fatal("no input files"); 95 return Args; 96 } 97 98 // Find a file by concatenating given paths. 99 static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) { 100 SmallString<128> S; 101 sys::path::append(S, Path1, Path2); 102 if (sys::fs::exists(S)) 103 return S.str().str(); 104 return None; 105 } 106 107 // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. 108 static std::string 109 searchLibrary(StringRef Name, ArrayRef<StringRef> SearchPaths, bool BStatic) { 110 if (Name.startswith(":")) { 111 for (StringRef Dir : SearchPaths) 112 if (Optional<std::string> S = findFile(Dir, Name.substr(1))) 113 return *S; 114 fatal("unable to find library -l" + Name); 115 } 116 117 for (StringRef Dir : SearchPaths) { 118 if (!BStatic) 119 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a")) 120 return *S; 121 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) 122 return *S; 123 } 124 fatal("unable to find library -l" + Name); 125 } 126 127 // Convert Unix-ish command line arguments to Windows-ish ones and 128 // then call coff::link. 129 bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) { 130 MinGWOptTable Parser; 131 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); 132 133 std::vector<std::string> LinkArgs; 134 auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); }; 135 136 Add("lld-link"); 137 Add("-lldmingw"); 138 139 if (auto *A = Args.getLastArg(OPT_entry)) { 140 StringRef S = A->getValue(); 141 if (Args.getLastArgValue(OPT_m) == "i386pe" && S.startswith("_")) 142 Add("-entry:" + S.substr(1)); 143 else 144 Add("-entry:" + S); 145 } 146 147 if (auto *A = Args.getLastArg(OPT_subs)) 148 Add("-subsystem:" + StringRef(A->getValue())); 149 if (auto *A = Args.getLastArg(OPT_out_implib)) 150 Add("-implib:" + StringRef(A->getValue())); 151 if (auto *A = Args.getLastArg(OPT_stack)) 152 Add("-stack:" + StringRef(A->getValue())); 153 if (auto *A = Args.getLastArg(OPT_output_def)) 154 Add("-output-def:" + StringRef(A->getValue())); 155 if (auto *A = Args.getLastArg(OPT_image_base)) 156 Add("-base:" + StringRef(A->getValue())); 157 if (auto *A = Args.getLastArg(OPT_map)) 158 Add("-lldmap:" + StringRef(A->getValue())); 159 160 if (auto *A = Args.getLastArg(OPT_o)) 161 Add("-out:" + StringRef(A->getValue())); 162 else if (Args.hasArg(OPT_shared)) 163 Add("-out:a.dll"); 164 else 165 Add("-out:a.exe"); 166 167 if (auto *A = Args.getLastArg(OPT_pdb)) { 168 Add("-debug"); 169 Add("-pdb:" + StringRef(A->getValue())); 170 } else if (Args.hasArg(OPT_strip_debug)) { 171 Add("-debug:symtab"); 172 } else if (!Args.hasArg(OPT_strip_all)) { 173 Add("-debug:dwarf"); 174 } 175 176 if (Args.hasArg(OPT_shared)) 177 Add("-dll"); 178 if (Args.hasArg(OPT_verbose)) 179 Add("-verbose"); 180 if (Args.hasArg(OPT_export_all_symbols)) 181 Add("-export-all-symbols"); 182 if (Args.hasArg(OPT_large_address_aware)) 183 Add("-largeaddressaware"); 184 if (Args.hasArg(OPT_kill_at)) 185 Add("-kill-at"); 186 187 if (Args.getLastArgValue(OPT_m) != "thumb2pe" && 188 Args.getLastArgValue(OPT_m) != "arm64pe" && !Args.hasArg(OPT_dynamicbase)) 189 Add("-dynamicbase:no"); 190 191 if (Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) 192 Add("-opt:ref"); 193 else 194 Add("-opt:noref"); 195 196 if (auto *A = Args.getLastArg(OPT_icf)) { 197 StringRef S = A->getValue(); 198 if (S == "all") 199 Add("-opt:icf"); 200 else if (S == "safe" || S == "none") 201 Add("-opt:noicf"); 202 else 203 fatal("unknown parameter: --icf=" + S); 204 } else { 205 Add("-opt:noicf"); 206 } 207 208 if (auto *A = Args.getLastArg(OPT_m)) { 209 StringRef S = A->getValue(); 210 if (S == "i386pe") 211 Add("-machine:x86"); 212 else if (S == "i386pep") 213 Add("-machine:x64"); 214 else if (S == "thumb2pe") 215 Add("-machine:arm"); 216 else if (S == "arm64pe") 217 Add("-machine:arm64"); 218 else 219 fatal("unknown parameter: -m" + S); 220 } 221 222 for (auto *A : Args.filtered(OPT_mllvm)) 223 Add("-mllvm:" + StringRef(A->getValue())); 224 225 for (auto *A : Args.filtered(OPT_Xlink)) 226 Add(A->getValue()); 227 228 if (Args.getLastArgValue(OPT_m) == "i386pe") 229 Add("-alternatename:__image_base__=___ImageBase"); 230 else 231 Add("-alternatename:__image_base__=__ImageBase"); 232 233 for (auto *A : Args.filtered(OPT_require_defined)) 234 Add("-include:" + StringRef(A->getValue())); 235 236 std::vector<StringRef> SearchPaths; 237 for (auto *A : Args.filtered(OPT_L)) { 238 SearchPaths.push_back(A->getValue()); 239 Add("-libpath:" + StringRef(A->getValue())); 240 } 241 242 StringRef Prefix = ""; 243 bool Static = false; 244 for (auto *A : Args) { 245 switch (A->getOption().getUnaliasedOption().getID()) { 246 case OPT_INPUT: 247 if (StringRef(A->getValue()).endswith_lower(".def")) 248 Add("-def:" + StringRef(A->getValue())); 249 else 250 Add(Prefix + StringRef(A->getValue())); 251 break; 252 case OPT_l: 253 Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static)); 254 break; 255 case OPT_whole_archive: 256 Prefix = "-wholearchive:"; 257 break; 258 case OPT_no_whole_archive: 259 Prefix = ""; 260 break; 261 case OPT_Bstatic: 262 Static = true; 263 break; 264 case OPT_Bdynamic: 265 Static = false; 266 break; 267 } 268 } 269 270 if (Args.hasArg(OPT_verbose) || Args.hasArg(OPT__HASH_HASH_HASH)) 271 outs() << llvm::join(LinkArgs, " ") << "\n"; 272 273 if (Args.hasArg(OPT__HASH_HASH_HASH)) 274 return true; 275 276 // Repack vector of strings to vector of const char pointers for coff::link. 277 std::vector<const char *> Vec; 278 for (const std::string &S : LinkArgs) 279 Vec.push_back(S.c_str()); 280 return coff::link(Vec, true); 281 } 282