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/CommonLinkerContext.h" 33 #include "lld/Common/ErrorHandler.h" 34 #include "lld/Common/Memory.h" 35 #include "lld/Common/Version.h" 36 #include "llvm/ADT/ArrayRef.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/Host.h" 46 #include "llvm/Support/Path.h" 47 #include <optional> 48 49 #if !defined(_MSC_VER) && !defined(__MINGW32__) 50 #include <unistd.h> 51 #endif 52 53 using namespace lld; 54 using namespace llvm; 55 56 // Create OptTable 57 enum { 58 OPT_INVALID = 0, 59 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, 60 #include "Options.inc" 61 #undef OPTION 62 }; 63 64 // Create prefix string literals used in Options.td 65 #define PREFIX(NAME, VALUE) \ 66 static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ 67 static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME( \ 68 NAME##_init, std::size(NAME##_init) - 1); 69 #include "Options.inc" 70 #undef PREFIX 71 72 // Create table mapping all options defined in Options.td 73 static constexpr opt::OptTable::Info infoTable[] = { 74 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 75 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ 76 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 77 #include "Options.inc" 78 #undef OPTION 79 }; 80 81 namespace { 82 class MinGWOptTable : public opt::GenericOptTable { 83 public: 84 MinGWOptTable() : opt::GenericOptTable(infoTable, false) {} 85 opt::InputArgList parse(ArrayRef<const char *> argv); 86 }; 87 } // namespace 88 89 static void printHelp(const char *argv0) { 90 MinGWOptTable().printHelp( 91 lld::outs(), (std::string(argv0) + " [options] file...").c_str(), "lld", 92 false /*ShowHidden*/, true /*ShowAllAliases*/); 93 lld::outs() << "\n"; 94 } 95 96 static cl::TokenizerCallback getQuotingStyle() { 97 if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32) 98 return cl::TokenizeWindowsCommandLine; 99 return cl::TokenizeGNUCommandLine; 100 } 101 102 opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> argv) { 103 unsigned missingIndex; 104 unsigned missingCount; 105 106 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size()); 107 cl::ExpandResponseFiles(saver(), getQuotingStyle(), vec); 108 opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); 109 110 if (missingCount) 111 error(StringRef(args.getArgString(missingIndex)) + ": missing argument"); 112 for (auto *arg : args.filtered(OPT_UNKNOWN)) 113 error("unknown argument: " + arg->getAsString(args)); 114 return args; 115 } 116 117 // Find a file by concatenating given paths. 118 static std::optional<std::string> findFile(StringRef path1, 119 const Twine &path2) { 120 SmallString<128> s; 121 sys::path::append(s, path1, path2); 122 if (sys::fs::exists(s)) 123 return std::string(s); 124 return std::nullopt; 125 } 126 127 // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. 128 static std::string 129 searchLibrary(StringRef name, ArrayRef<StringRef> searchPaths, bool bStatic) { 130 if (name.startswith(":")) { 131 for (StringRef dir : searchPaths) 132 if (std::optional<std::string> s = findFile(dir, name.substr(1))) 133 return *s; 134 error("unable to find library -l" + name); 135 return ""; 136 } 137 138 for (StringRef dir : searchPaths) { 139 if (!bStatic) { 140 if (std::optional<std::string> s = findFile(dir, "lib" + name + ".dll.a")) 141 return *s; 142 if (std::optional<std::string> s = findFile(dir, name + ".dll.a")) 143 return *s; 144 } 145 if (std::optional<std::string> s = findFile(dir, "lib" + name + ".a")) 146 return *s; 147 if (std::optional<std::string> s = findFile(dir, name + ".lib")) 148 return *s; 149 if (!bStatic) { 150 if (std::optional<std::string> s = findFile(dir, "lib" + name + ".dll")) 151 return *s; 152 if (std::optional<std::string> s = findFile(dir, name + ".dll")) 153 return *s; 154 } 155 } 156 error("unable to find library -l" + name); 157 return ""; 158 } 159 160 // Convert Unix-ish command line arguments to Windows-ish ones and 161 // then call coff::link. 162 bool mingw::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, 163 llvm::raw_ostream &stderrOS, bool exitEarly, 164 bool disableOutput) { 165 auto *ctx = new CommonLinkerContext; 166 ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput); 167 168 MinGWOptTable parser; 169 opt::InputArgList args = parser.parse(argsArr.slice(1)); 170 171 if (errorCount()) 172 return false; 173 174 if (args.hasArg(OPT_help)) { 175 printHelp(argsArr[0]); 176 return true; 177 } 178 179 // A note about "compatible with GNU linkers" message: this is a hack for 180 // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and 181 // still the newest version in March 2017) or earlier to recognize LLD as 182 // a GNU compatible linker. As long as an output for the -v option 183 // contains "GNU" or "with BFD", they recognize us as GNU-compatible. 184 if (args.hasArg(OPT_v) || args.hasArg(OPT_version)) 185 message(getLLDVersion() + " (compatible with GNU linkers)"); 186 187 // The behavior of -v or --version is a bit strange, but this is 188 // needed for compatibility with GNU linkers. 189 if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) 190 return true; 191 if (args.hasArg(OPT_version)) 192 return true; 193 194 if (!args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) { 195 error("no input files"); 196 return false; 197 } 198 199 std::vector<std::string> linkArgs; 200 auto add = [&](const Twine &s) { linkArgs.push_back(s.str()); }; 201 202 add("lld-link"); 203 add("-lldmingw"); 204 205 if (auto *a = args.getLastArg(OPT_entry)) { 206 StringRef s = a->getValue(); 207 if (args.getLastArgValue(OPT_m) == "i386pe" && s.startswith("_")) 208 add("-entry:" + s.substr(1)); 209 else 210 add("-entry:" + s); 211 } 212 213 if (args.hasArg(OPT_major_os_version, OPT_minor_os_version, 214 OPT_major_subsystem_version, OPT_minor_subsystem_version)) { 215 StringRef majOSVer = args.getLastArgValue(OPT_major_os_version, "6"); 216 StringRef minOSVer = args.getLastArgValue(OPT_minor_os_version, "0"); 217 StringRef majSubSysVer = "6"; 218 StringRef minSubSysVer = "0"; 219 StringRef subSysName = "default"; 220 StringRef subSysVer; 221 // Iterate over --{major,minor}-subsystem-version and --subsystem, and pick 222 // the version number components from the last one of them that specifies 223 // a version. 224 for (auto *a : args.filtered(OPT_major_subsystem_version, 225 OPT_minor_subsystem_version, OPT_subs)) { 226 switch (a->getOption().getID()) { 227 case OPT_major_subsystem_version: 228 majSubSysVer = a->getValue(); 229 break; 230 case OPT_minor_subsystem_version: 231 minSubSysVer = a->getValue(); 232 break; 233 case OPT_subs: 234 std::tie(subSysName, subSysVer) = StringRef(a->getValue()).split(':'); 235 if (!subSysVer.empty()) { 236 if (subSysVer.contains('.')) 237 std::tie(majSubSysVer, minSubSysVer) = subSysVer.split('.'); 238 else 239 majSubSysVer = subSysVer; 240 } 241 break; 242 } 243 } 244 add("-osversion:" + majOSVer + "." + minOSVer); 245 add("-subsystem:" + subSysName + "," + majSubSysVer + "." + minSubSysVer); 246 } else if (args.hasArg(OPT_subs)) { 247 StringRef subSys = args.getLastArgValue(OPT_subs, "default"); 248 StringRef subSysName, subSysVer; 249 std::tie(subSysName, subSysVer) = subSys.split(':'); 250 StringRef sep = subSysVer.empty() ? "" : ","; 251 add("-subsystem:" + subSysName + sep + subSysVer); 252 } 253 254 if (auto *a = args.getLastArg(OPT_out_implib)) 255 add("-implib:" + StringRef(a->getValue())); 256 if (auto *a = args.getLastArg(OPT_stack)) 257 add("-stack:" + StringRef(a->getValue())); 258 if (auto *a = args.getLastArg(OPT_output_def)) 259 add("-output-def:" + StringRef(a->getValue())); 260 if (auto *a = args.getLastArg(OPT_image_base)) 261 add("-base:" + StringRef(a->getValue())); 262 if (auto *a = args.getLastArg(OPT_map)) 263 add("-lldmap:" + StringRef(a->getValue())); 264 if (auto *a = args.getLastArg(OPT_reproduce)) 265 add("-reproduce:" + StringRef(a->getValue())); 266 if (auto *a = args.getLastArg(OPT_thinlto_cache_dir)) 267 add("-lldltocache:" + StringRef(a->getValue())); 268 if (auto *a = args.getLastArg(OPT_file_alignment)) 269 add("-filealign:" + StringRef(a->getValue())); 270 if (auto *a = args.getLastArg(OPT_section_alignment)) 271 add("-align:" + StringRef(a->getValue())); 272 if (auto *a = args.getLastArg(OPT_heap)) 273 add("-heap:" + StringRef(a->getValue())); 274 275 if (auto *a = args.getLastArg(OPT_o)) 276 add("-out:" + StringRef(a->getValue())); 277 else if (args.hasArg(OPT_shared)) 278 add("-out:a.dll"); 279 else 280 add("-out:a.exe"); 281 282 if (auto *a = args.getLastArg(OPT_pdb)) { 283 add("-debug"); 284 StringRef v = a->getValue(); 285 if (!v.empty()) 286 add("-pdb:" + v); 287 } else if (args.hasArg(OPT_strip_debug)) { 288 add("-debug:symtab"); 289 } else if (!args.hasArg(OPT_strip_all)) { 290 add("-debug:dwarf"); 291 } 292 293 if (args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false)) 294 add("-WX"); 295 else 296 add("-WX:no"); 297 298 if (args.hasFlag(OPT_enable_stdcall_fixup, OPT_disable_stdcall_fixup, false)) 299 add("-stdcall-fixup"); 300 else if (args.hasArg(OPT_disable_stdcall_fixup)) 301 add("-stdcall-fixup:no"); 302 303 if (args.hasArg(OPT_shared)) 304 add("-dll"); 305 if (args.hasArg(OPT_verbose)) 306 add("-verbose"); 307 if (args.hasArg(OPT_exclude_all_symbols)) 308 add("-exclude-all-symbols"); 309 if (args.hasArg(OPT_export_all_symbols)) 310 add("-export-all-symbols"); 311 if (args.hasArg(OPT_large_address_aware)) 312 add("-largeaddressaware"); 313 if (args.hasArg(OPT_kill_at)) 314 add("-kill-at"); 315 if (args.hasArg(OPT_appcontainer)) 316 add("-appcontainer"); 317 if (args.hasFlag(OPT_no_seh, OPT_disable_no_seh, false)) 318 add("-noseh"); 319 320 if (args.getLastArgValue(OPT_m) != "thumb2pe" && 321 args.getLastArgValue(OPT_m) != "arm64pe" && 322 args.hasFlag(OPT_disable_dynamicbase, OPT_dynamicbase, false)) 323 add("-dynamicbase:no"); 324 if (args.hasFlag(OPT_disable_high_entropy_va, OPT_high_entropy_va, false)) 325 add("-highentropyva:no"); 326 if (args.hasFlag(OPT_disable_nxcompat, OPT_nxcompat, false)) 327 add("-nxcompat:no"); 328 if (args.hasFlag(OPT_disable_tsaware, OPT_tsaware, false)) 329 add("-tsaware:no"); 330 331 if (args.hasFlag(OPT_disable_reloc_section, OPT_enable_reloc_section, false)) 332 add("-fixed"); 333 334 if (args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false)) 335 add("-timestamp:0"); 336 337 if (args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) 338 add("-opt:ref"); 339 else 340 add("-opt:noref"); 341 342 if (args.hasFlag(OPT_demangle, OPT_no_demangle, true)) 343 add("-demangle"); 344 else 345 add("-demangle:no"); 346 347 if (args.hasFlag(OPT_enable_auto_import, OPT_disable_auto_import, true)) 348 add("-auto-import"); 349 else 350 add("-auto-import:no"); 351 if (args.hasFlag(OPT_enable_runtime_pseudo_reloc, 352 OPT_disable_runtime_pseudo_reloc, true)) 353 add("-runtime-pseudo-reloc"); 354 else 355 add("-runtime-pseudo-reloc:no"); 356 357 if (args.hasFlag(OPT_allow_multiple_definition, 358 OPT_no_allow_multiple_definition, false)) 359 add("-force:multiple"); 360 361 if (auto *a = args.getLastArg(OPT_icf)) { 362 StringRef s = a->getValue(); 363 if (s == "all") 364 add("-opt:icf"); 365 else if (s == "safe" || s == "none") 366 add("-opt:noicf"); 367 else 368 error("unknown parameter: --icf=" + s); 369 } else { 370 add("-opt:noicf"); 371 } 372 373 if (auto *a = args.getLastArg(OPT_m)) { 374 StringRef s = a->getValue(); 375 if (s == "i386pe") 376 add("-machine:x86"); 377 else if (s == "i386pep") 378 add("-machine:x64"); 379 else if (s == "thumb2pe") 380 add("-machine:arm"); 381 else if (s == "arm64pe") 382 add("-machine:arm64"); 383 else 384 error("unknown parameter: -m" + s); 385 } 386 387 if (args.hasFlag(OPT_guard_cf, OPT_no_guard_cf, false)) { 388 if (args.hasFlag(OPT_guard_longjmp, OPT_no_guard_longjmp, true)) 389 add("-guard:cf,longjmp"); 390 else 391 add("-guard:cf,nolongjmp"); 392 } else if (args.hasFlag(OPT_guard_longjmp, OPT_no_guard_longjmp, false)) { 393 auto *a = args.getLastArg(OPT_guard_longjmp); 394 warn("parameter " + a->getSpelling() + 395 " only takes effect when used with --guard-cf"); 396 } 397 398 if (auto *a = args.getLastArg(OPT_error_limit)) { 399 int n; 400 StringRef s = a->getValue(); 401 if (s.getAsInteger(10, n)) 402 error(a->getSpelling() + ": number expected, but got " + s); 403 else 404 add("-errorlimit:" + s); 405 } 406 407 for (auto *a : args.filtered(OPT_mllvm)) 408 add("-mllvm:" + StringRef(a->getValue())); 409 410 for (auto *a : args.filtered(OPT_Xlink)) 411 add(a->getValue()); 412 413 if (args.getLastArgValue(OPT_m) == "i386pe") 414 add("-alternatename:__image_base__=___ImageBase"); 415 else 416 add("-alternatename:__image_base__=__ImageBase"); 417 418 for (auto *a : args.filtered(OPT_require_defined)) 419 add("-include:" + StringRef(a->getValue())); 420 for (auto *a : args.filtered(OPT_undefined)) 421 add("-includeoptional:" + StringRef(a->getValue())); 422 for (auto *a : args.filtered(OPT_delayload)) 423 add("-delayload:" + StringRef(a->getValue())); 424 for (auto *a : args.filtered(OPT_wrap)) 425 add("-wrap:" + StringRef(a->getValue())); 426 for (auto *a : args.filtered(OPT_exclude_symbols)) 427 add("-exclude-symbols:" + StringRef(a->getValue())); 428 429 std::vector<StringRef> searchPaths; 430 for (auto *a : args.filtered(OPT_L)) { 431 searchPaths.push_back(a->getValue()); 432 add("-libpath:" + StringRef(a->getValue())); 433 } 434 435 StringRef prefix = ""; 436 bool isStatic = false; 437 for (auto *a : args) { 438 switch (a->getOption().getID()) { 439 case OPT_INPUT: 440 if (StringRef(a->getValue()).endswith_insensitive(".def")) 441 add("-def:" + StringRef(a->getValue())); 442 else 443 add(prefix + StringRef(a->getValue())); 444 break; 445 case OPT_l: 446 add(prefix + searchLibrary(a->getValue(), searchPaths, isStatic)); 447 break; 448 case OPT_whole_archive: 449 prefix = "-wholearchive:"; 450 break; 451 case OPT_no_whole_archive: 452 prefix = ""; 453 break; 454 case OPT_Bstatic: 455 isStatic = true; 456 break; 457 case OPT_Bdynamic: 458 isStatic = false; 459 break; 460 } 461 } 462 463 if (errorCount()) 464 return false; 465 466 if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH)) 467 lld::errs() << llvm::join(linkArgs, " ") << "\n"; 468 469 if (args.hasArg(OPT__HASH_HASH_HASH)) 470 return true; 471 472 // Repack vector of strings to vector of const char pointers for coff::link. 473 std::vector<const char *> vec; 474 for (const std::string &s : linkArgs) 475 vec.push_back(s.c_str()); 476 // Pass the actual binary name, to make error messages be printed with 477 // the right prefix. 478 vec[0] = argsArr[0]; 479 480 // The context will be re-created in the COFF driver. 481 lld::CommonLinkerContext::destroy(); 482 483 return coff::link(vec, stdoutOS, stderrOS, exitEarly, disableOutput); 484 } 485