1 //===- MinGW/Driver.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 // MinGW is a GNU development environment for Windows. It consists of GNU 10 // tools such as GCC and GNU ld. Unlike Cygwin, there's no POSIX-compatible 11 // layer, as it aims to be a native development toolchain. 12 // 13 // lld/MinGW is a drop-in replacement for GNU ld/MinGW. 14 // 15 // Being a native development tool, a MinGW linker is not very different from 16 // Microsoft link.exe, so a MinGW linker can be implemented as a thin wrapper 17 // for lld/COFF. This driver takes Unix-ish command line options, translates 18 // them to Windows-ish ones, and then passes them to lld/COFF. 19 // 20 // When this driver calls the lld/COFF driver, it passes a hidden option 21 // "-lldmingw" along with other user-supplied options, to run the lld/COFF 22 // linker in "MinGW mode". 23 // 24 // There are subtle differences between MS link.exe and GNU ld/MinGW, and GNU 25 // ld/MinGW implements a few GNU-specific features. Such features are directly 26 // implemented in lld/COFF and enabled only when the linker is running in MinGW 27 // mode. 28 // 29 //===----------------------------------------------------------------------===// 30 31 #include "lld/Common/Driver.h" 32 #include "lld/Common/ErrorHandler.h" 33 #include "lld/Common/Memory.h" 34 #include "lld/Common/Version.h" 35 #include "llvm/ADT/ArrayRef.h" 36 #include "llvm/ADT/Optional.h" 37 #include "llvm/ADT/StringExtras.h" 38 #include "llvm/ADT/StringRef.h" 39 #include "llvm/ADT/Triple.h" 40 #include "llvm/Option/Arg.h" 41 #include "llvm/Option/ArgList.h" 42 #include "llvm/Option/Option.h" 43 #include "llvm/Support/CommandLine.h" 44 #include "llvm/Support/FileSystem.h" 45 #include "llvm/Support/Path.h" 46 47 #if !defined(_MSC_VER) && !defined(__MINGW32__) 48 #include <unistd.h> 49 #endif 50 51 using namespace lld; 52 using namespace llvm; 53 54 // Create OptTable 55 enum { 56 OPT_INVALID = 0, 57 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, 58 #include "Options.inc" 59 #undef OPTION 60 }; 61 62 // Create prefix string literals used in Options.td 63 #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; 64 #include "Options.inc" 65 #undef PREFIX 66 67 // Create table mapping all options defined in Options.td 68 static const opt::OptTable::Info InfoTable[] = { 69 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 70 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ 71 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 72 #include "Options.inc" 73 #undef OPTION 74 }; 75 76 namespace { 77 class MinGWOptTable : public opt::OptTable { 78 public: 79 MinGWOptTable() : OptTable(InfoTable, false) {} 80 opt::InputArgList parse(ArrayRef<const char *> Argv); 81 }; 82 } // namespace 83 84 static void printHelp(const char *Argv0) { 85 MinGWOptTable().PrintHelp( 86 outs(), (std::string(Argv0) + " [options] file...").c_str(), "lld", 87 false /*ShowHidden*/, true /*ShowAllAliases*/); 88 outs() << "\n"; 89 } 90 91 static cl::TokenizerCallback getQuotingStyle() { 92 if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32) 93 return cl::TokenizeWindowsCommandLine; 94 return cl::TokenizeGNUCommandLine; 95 } 96 97 opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> Argv) { 98 unsigned MissingIndex; 99 unsigned MissingCount; 100 101 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); 102 cl::ExpandResponseFiles(Saver, getQuotingStyle(), Vec); 103 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); 104 105 if (MissingCount) 106 fatal(StringRef(Args.getArgString(MissingIndex)) + ": missing argument"); 107 for (auto *Arg : Args.filtered(OPT_UNKNOWN)) 108 fatal("unknown argument: " + Arg->getSpelling()); 109 return Args; 110 } 111 112 // Find a file by concatenating given paths. 113 static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) { 114 SmallString<128> S; 115 sys::path::append(S, Path1, Path2); 116 if (sys::fs::exists(S)) 117 return S.str().str(); 118 return None; 119 } 120 121 // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. 122 static std::string 123 searchLibrary(StringRef Name, ArrayRef<StringRef> SearchPaths, bool BStatic) { 124 if (Name.startswith(":")) { 125 for (StringRef Dir : SearchPaths) 126 if (Optional<std::string> S = findFile(Dir, Name.substr(1))) 127 return *S; 128 fatal("unable to find library -l" + Name); 129 } 130 131 for (StringRef Dir : SearchPaths) { 132 if (!BStatic) 133 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a")) 134 return *S; 135 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) 136 return *S; 137 } 138 fatal("unable to find library -l" + Name); 139 } 140 141 // Convert Unix-ish command line arguments to Windows-ish ones and 142 // then call coff::link. 143 bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) { 144 MinGWOptTable Parser; 145 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); 146 147 if (Args.hasArg(OPT_help)) { 148 printHelp(ArgsArr[0]); 149 return true; 150 } 151 152 // A note about "compatible with GNU linkers" message: this is a hack for 153 // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and 154 // still the newest version in March 2017) or earlier to recognize LLD as 155 // a GNU compatible linker. As long as an output for the -v option 156 // contains "GNU" or "with BFD", they recognize us as GNU-compatible. 157 if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) 158 message(getLLDVersion() + " (compatible with GNU linkers)"); 159 160 // The behavior of -v or --version is a bit strange, but this is 161 // needed for compatibility with GNU linkers. 162 if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l)) 163 return true; 164 if (Args.hasArg(OPT_version)) 165 return true; 166 167 if (!Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l)) 168 fatal("no input files"); 169 170 std::vector<std::string> LinkArgs; 171 auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); }; 172 173 Add("lld-link"); 174 Add("-lldmingw"); 175 176 if (auto *A = Args.getLastArg(OPT_entry)) { 177 StringRef S = A->getValue(); 178 if (Args.getLastArgValue(OPT_m) == "i386pe" && S.startswith("_")) 179 Add("-entry:" + S.substr(1)); 180 else 181 Add("-entry:" + S); 182 } 183 184 if (Args.hasArg(OPT_major_os_version, OPT_minor_os_version, 185 OPT_major_subsystem_version, OPT_minor_subsystem_version)) { 186 auto *MajOSVer = Args.getLastArg(OPT_major_os_version); 187 auto *MinOSVer = Args.getLastArg(OPT_minor_os_version); 188 auto *MajSubSysVer = Args.getLastArg(OPT_major_subsystem_version); 189 auto *MinSubSysVer = Args.getLastArg(OPT_minor_subsystem_version); 190 if (MajOSVer && MajSubSysVer && 191 StringRef(MajOSVer->getValue()) != StringRef(MajSubSysVer->getValue())) 192 warn("--major-os-version and --major-subsystem-version set to differing " 193 "versions, not supported"); 194 if (MinOSVer && MinSubSysVer && 195 StringRef(MinOSVer->getValue()) != StringRef(MinSubSysVer->getValue())) 196 warn("--minor-os-version and --minor-subsystem-version set to differing " 197 "versions, not supported"); 198 StringRef SubSys = Args.getLastArgValue(OPT_subs, "default"); 199 StringRef Major = MajOSVer ? MajOSVer->getValue() 200 : MajSubSysVer ? MajSubSysVer->getValue() : "6"; 201 StringRef Minor = MinOSVer ? MinOSVer->getValue() 202 : MinSubSysVer ? MinSubSysVer->getValue() : ""; 203 StringRef Sep = Minor.empty() ? "" : "."; 204 Add("-subsystem:" + SubSys + "," + Major + Sep + Minor); 205 } else if (auto *A = Args.getLastArg(OPT_subs)) { 206 Add("-subsystem:" + StringRef(A->getValue())); 207 } 208 209 if (auto *A = Args.getLastArg(OPT_out_implib)) 210 Add("-implib:" + StringRef(A->getValue())); 211 if (auto *A = Args.getLastArg(OPT_stack)) 212 Add("-stack:" + StringRef(A->getValue())); 213 if (auto *A = Args.getLastArg(OPT_output_def)) 214 Add("-output-def:" + StringRef(A->getValue())); 215 if (auto *A = Args.getLastArg(OPT_image_base)) 216 Add("-base:" + StringRef(A->getValue())); 217 if (auto *A = Args.getLastArg(OPT_map)) 218 Add("-lldmap:" + StringRef(A->getValue())); 219 220 if (auto *A = Args.getLastArg(OPT_o)) 221 Add("-out:" + StringRef(A->getValue())); 222 else if (Args.hasArg(OPT_shared)) 223 Add("-out:a.dll"); 224 else 225 Add("-out:a.exe"); 226 227 if (auto *A = Args.getLastArg(OPT_pdb)) { 228 Add("-debug"); 229 StringRef V = A->getValue(); 230 if (!V.empty()) 231 Add("-pdb:" + V); 232 } else if (Args.hasArg(OPT_strip_debug)) { 233 Add("-debug:symtab"); 234 } else if (!Args.hasArg(OPT_strip_all)) { 235 Add("-debug:dwarf"); 236 } 237 238 if (Args.hasArg(OPT_shared)) 239 Add("-dll"); 240 if (Args.hasArg(OPT_verbose)) 241 Add("-verbose"); 242 if (Args.hasArg(OPT_exclude_all_symbols)) 243 Add("-exclude-all-symbols"); 244 if (Args.hasArg(OPT_export_all_symbols)) 245 Add("-export-all-symbols"); 246 if (Args.hasArg(OPT_large_address_aware)) 247 Add("-largeaddressaware"); 248 if (Args.hasArg(OPT_kill_at)) 249 Add("-kill-at"); 250 if (Args.hasArg(OPT_appcontainer)) 251 Add("-appcontainer"); 252 253 if (Args.getLastArgValue(OPT_m) != "thumb2pe" && 254 Args.getLastArgValue(OPT_m) != "arm64pe" && !Args.hasArg(OPT_dynamicbase)) 255 Add("-dynamicbase:no"); 256 257 if (Args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false)) 258 Add("-timestamp:0"); 259 260 if (Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) 261 Add("-opt:ref"); 262 else 263 Add("-opt:noref"); 264 265 if (auto *A = Args.getLastArg(OPT_icf)) { 266 StringRef S = A->getValue(); 267 if (S == "all") 268 Add("-opt:icf"); 269 else if (S == "safe" || S == "none") 270 Add("-opt:noicf"); 271 else 272 fatal("unknown parameter: --icf=" + S); 273 } else { 274 Add("-opt:noicf"); 275 } 276 277 if (auto *A = Args.getLastArg(OPT_m)) { 278 StringRef S = A->getValue(); 279 if (S == "i386pe") 280 Add("-machine:x86"); 281 else if (S == "i386pep") 282 Add("-machine:x64"); 283 else if (S == "thumb2pe") 284 Add("-machine:arm"); 285 else if (S == "arm64pe") 286 Add("-machine:arm64"); 287 else 288 fatal("unknown parameter: -m" + S); 289 } 290 291 for (auto *A : Args.filtered(OPT_mllvm)) 292 Add("-mllvm:" + StringRef(A->getValue())); 293 294 for (auto *A : Args.filtered(OPT_Xlink)) 295 Add(A->getValue()); 296 297 if (Args.getLastArgValue(OPT_m) == "i386pe") 298 Add("-alternatename:__image_base__=___ImageBase"); 299 else 300 Add("-alternatename:__image_base__=__ImageBase"); 301 302 for (auto *A : Args.filtered(OPT_require_defined)) 303 Add("-include:" + StringRef(A->getValue())); 304 for (auto *A : Args.filtered(OPT_undefined)) 305 Add("-includeoptional:" + StringRef(A->getValue())); 306 307 std::vector<StringRef> SearchPaths; 308 for (auto *A : Args.filtered(OPT_L)) { 309 SearchPaths.push_back(A->getValue()); 310 Add("-libpath:" + StringRef(A->getValue())); 311 } 312 313 StringRef Prefix = ""; 314 bool Static = false; 315 for (auto *A : Args) { 316 switch (A->getOption().getUnaliasedOption().getID()) { 317 case OPT_INPUT: 318 if (StringRef(A->getValue()).endswith_lower(".def")) 319 Add("-def:" + StringRef(A->getValue())); 320 else 321 Add(Prefix + StringRef(A->getValue())); 322 break; 323 case OPT_l: 324 Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static)); 325 break; 326 case OPT_whole_archive: 327 Prefix = "-wholearchive:"; 328 break; 329 case OPT_no_whole_archive: 330 Prefix = ""; 331 break; 332 case OPT_Bstatic: 333 Static = true; 334 break; 335 case OPT_Bdynamic: 336 Static = false; 337 break; 338 } 339 } 340 341 if (Args.hasArg(OPT_verbose) || Args.hasArg(OPT__HASH_HASH_HASH)) 342 outs() << llvm::join(LinkArgs, " ") << "\n"; 343 344 if (Args.hasArg(OPT__HASH_HASH_HASH)) 345 return true; 346 347 // Repack vector of strings to vector of const char pointers for coff::link. 348 std::vector<const char *> Vec; 349 for (const std::string &S : LinkArgs) 350 Vec.push_back(S.c_str()); 351 return coff::link(Vec, true); 352 } 353