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 error(StringRef(args.getArgString(missingIndex)) + ": missing argument"); 107 for (auto *arg : args.filtered(OPT_UNKNOWN)) 108 error("unknown argument: " + arg->getAsString(args)); 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 error("unable to find library -l" + name); 129 return ""; 130 } 131 132 for (StringRef dir : searchPaths) { 133 if (!bStatic) { 134 if (Optional<std::string> s = findFile(dir, "lib" + name + ".dll.a")) 135 return *s; 136 if (Optional<std::string> s = findFile(dir, name + ".dll.a")) 137 return *s; 138 } 139 if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) 140 return *s; 141 if (!bStatic) { 142 if (Optional<std::string> s = findFile(dir, name + ".lib")) 143 return *s; 144 if (Optional<std::string> s = findFile(dir, "lib" + name + ".dll")) { 145 error("lld doesn't support linking directly against " + *s + 146 ", use an import library"); 147 return ""; 148 } 149 if (Optional<std::string> s = findFile(dir, name + ".dll")) { 150 error("lld doesn't support linking directly against " + *s + 151 ", use an import library"); 152 return ""; 153 } 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, raw_ostream &diag) { 163 enableColors(diag.has_colors()); 164 165 MinGWOptTable parser; 166 opt::InputArgList args = parser.parse(argsArr.slice(1)); 167 168 if (errorCount()) 169 return false; 170 171 if (args.hasArg(OPT_help)) { 172 printHelp(argsArr[0]); 173 return true; 174 } 175 176 // A note about "compatible with GNU linkers" message: this is a hack for 177 // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and 178 // still the newest version in March 2017) or earlier to recognize LLD as 179 // a GNU compatible linker. As long as an output for the -v option 180 // contains "GNU" or "with BFD", they recognize us as GNU-compatible. 181 if (args.hasArg(OPT_v) || args.hasArg(OPT_version)) 182 message(getLLDVersion() + " (compatible with GNU linkers)"); 183 184 // The behavior of -v or --version is a bit strange, but this is 185 // needed for compatibility with GNU linkers. 186 if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) 187 return true; 188 if (args.hasArg(OPT_version)) 189 return true; 190 191 if (!args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) { 192 error("no input files"); 193 return false; 194 } 195 196 std::vector<std::string> linkArgs; 197 auto add = [&](const Twine &s) { linkArgs.push_back(s.str()); }; 198 199 add("lld-link"); 200 add("-lldmingw"); 201 202 if (auto *a = args.getLastArg(OPT_entry)) { 203 StringRef s = a->getValue(); 204 if (args.getLastArgValue(OPT_m) == "i386pe" && s.startswith("_")) 205 add("-entry:" + s.substr(1)); 206 else 207 add("-entry:" + s); 208 } 209 210 if (args.hasArg(OPT_major_os_version, OPT_minor_os_version, 211 OPT_major_subsystem_version, OPT_minor_subsystem_version)) { 212 auto *majOSVer = args.getLastArg(OPT_major_os_version); 213 auto *minOSVer = args.getLastArg(OPT_minor_os_version); 214 auto *majSubSysVer = args.getLastArg(OPT_major_subsystem_version); 215 auto *minSubSysVer = args.getLastArg(OPT_minor_subsystem_version); 216 if (majOSVer && majSubSysVer && 217 StringRef(majOSVer->getValue()) != StringRef(majSubSysVer->getValue())) 218 warn("--major-os-version and --major-subsystem-version set to differing " 219 "versions, not supported"); 220 if (minOSVer && minSubSysVer && 221 StringRef(minOSVer->getValue()) != StringRef(minSubSysVer->getValue())) 222 warn("--minor-os-version and --minor-subsystem-version set to differing " 223 "versions, not supported"); 224 StringRef subSys = args.getLastArgValue(OPT_subs, "default"); 225 StringRef major = majOSVer ? majOSVer->getValue() 226 : majSubSysVer ? majSubSysVer->getValue() : "6"; 227 StringRef minor = minOSVer ? minOSVer->getValue() 228 : minSubSysVer ? minSubSysVer->getValue() : ""; 229 StringRef sep = minor.empty() ? "" : "."; 230 add("-subsystem:" + subSys + "," + major + sep + minor); 231 } else if (auto *a = args.getLastArg(OPT_subs)) { 232 add("-subsystem:" + StringRef(a->getValue())); 233 } 234 235 if (auto *a = args.getLastArg(OPT_out_implib)) 236 add("-implib:" + StringRef(a->getValue())); 237 if (auto *a = args.getLastArg(OPT_stack)) 238 add("-stack:" + StringRef(a->getValue())); 239 if (auto *a = args.getLastArg(OPT_output_def)) 240 add("-output-def:" + StringRef(a->getValue())); 241 if (auto *a = args.getLastArg(OPT_image_base)) 242 add("-base:" + StringRef(a->getValue())); 243 if (auto *a = args.getLastArg(OPT_map)) 244 add("-lldmap:" + StringRef(a->getValue())); 245 if (auto *a = args.getLastArg(OPT_reproduce)) 246 add("-reproduce:" + StringRef(a->getValue())); 247 248 if (auto *a = args.getLastArg(OPT_o)) 249 add("-out:" + StringRef(a->getValue())); 250 else if (args.hasArg(OPT_shared)) 251 add("-out:a.dll"); 252 else 253 add("-out:a.exe"); 254 255 if (auto *a = args.getLastArg(OPT_pdb)) { 256 add("-debug"); 257 StringRef v = a->getValue(); 258 if (!v.empty()) 259 add("-pdb:" + v); 260 } else if (args.hasArg(OPT_strip_debug)) { 261 add("-debug:symtab"); 262 } else if (!args.hasArg(OPT_strip_all)) { 263 add("-debug:dwarf"); 264 } 265 266 if (args.hasArg(OPT_shared)) 267 add("-dll"); 268 if (args.hasArg(OPT_verbose)) 269 add("-verbose"); 270 if (args.hasArg(OPT_exclude_all_symbols)) 271 add("-exclude-all-symbols"); 272 if (args.hasArg(OPT_export_all_symbols)) 273 add("-export-all-symbols"); 274 if (args.hasArg(OPT_large_address_aware)) 275 add("-largeaddressaware"); 276 if (args.hasArg(OPT_kill_at)) 277 add("-kill-at"); 278 if (args.hasArg(OPT_appcontainer)) 279 add("-appcontainer"); 280 281 if (args.getLastArgValue(OPT_m) != "thumb2pe" && 282 args.getLastArgValue(OPT_m) != "arm64pe" && !args.hasArg(OPT_dynamicbase)) 283 add("-dynamicbase:no"); 284 285 if (args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false)) 286 add("-timestamp:0"); 287 288 if (args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) 289 add("-opt:ref"); 290 else 291 add("-opt:noref"); 292 293 if (auto *a = args.getLastArg(OPT_icf)) { 294 StringRef s = a->getValue(); 295 if (s == "all") 296 add("-opt:icf"); 297 else if (s == "safe" || s == "none") 298 add("-opt:noicf"); 299 else 300 error("unknown parameter: --icf=" + s); 301 } else { 302 add("-opt:noicf"); 303 } 304 305 if (auto *a = args.getLastArg(OPT_m)) { 306 StringRef s = a->getValue(); 307 if (s == "i386pe") 308 add("-machine:x86"); 309 else if (s == "i386pep") 310 add("-machine:x64"); 311 else if (s == "thumb2pe") 312 add("-machine:arm"); 313 else if (s == "arm64pe") 314 add("-machine:arm64"); 315 else 316 error("unknown parameter: -m" + s); 317 } 318 319 for (auto *a : args.filtered(OPT_mllvm)) 320 add("-mllvm:" + StringRef(a->getValue())); 321 322 for (auto *a : args.filtered(OPT_Xlink)) 323 add(a->getValue()); 324 325 if (args.getLastArgValue(OPT_m) == "i386pe") 326 add("-alternatename:__image_base__=___ImageBase"); 327 else 328 add("-alternatename:__image_base__=__ImageBase"); 329 330 for (auto *a : args.filtered(OPT_require_defined)) 331 add("-include:" + StringRef(a->getValue())); 332 for (auto *a : args.filtered(OPT_undefined)) 333 add("-includeoptional:" + StringRef(a->getValue())); 334 for (auto *a : args.filtered(OPT_delayload)) 335 add("-delayload:" + StringRef(a->getValue())); 336 337 std::vector<StringRef> searchPaths; 338 for (auto *a : args.filtered(OPT_L)) { 339 searchPaths.push_back(a->getValue()); 340 add("-libpath:" + StringRef(a->getValue())); 341 } 342 343 StringRef prefix = ""; 344 bool isStatic = false; 345 for (auto *a : args) { 346 switch (a->getOption().getID()) { 347 case OPT_INPUT: 348 if (StringRef(a->getValue()).endswith_lower(".def")) 349 add("-def:" + StringRef(a->getValue())); 350 else 351 add(prefix + StringRef(a->getValue())); 352 break; 353 case OPT_l: 354 add(prefix + searchLibrary(a->getValue(), searchPaths, isStatic)); 355 break; 356 case OPT_whole_archive: 357 prefix = "-wholearchive:"; 358 break; 359 case OPT_no_whole_archive: 360 prefix = ""; 361 break; 362 case OPT_Bstatic: 363 isStatic = true; 364 break; 365 case OPT_Bdynamic: 366 isStatic = false; 367 break; 368 } 369 } 370 371 if (errorCount()) 372 return false; 373 374 if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH)) 375 outs() << llvm::join(linkArgs, " ") << "\n"; 376 377 if (args.hasArg(OPT__HASH_HASH_HASH)) 378 return true; 379 380 // Repack vector of strings to vector of const char pointers for coff::link. 381 std::vector<const char *> vec; 382 for (const std::string &s : linkArgs) 383 vec.push_back(s.c_str()); 384 return coff::link(vec, true); 385 } 386