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->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 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 for (auto *a : args.filtered(OPT_delayload)) 307 add("-delayload:" + StringRef(a->getValue())); 308 309 std::vector<StringRef> searchPaths; 310 for (auto *a : args.filtered(OPT_L)) { 311 searchPaths.push_back(a->getValue()); 312 add("-libpath:" + StringRef(a->getValue())); 313 } 314 315 StringRef prefix = ""; 316 bool isStatic = false; 317 for (auto *a : args) { 318 switch (a->getOption().getID()) { 319 case OPT_INPUT: 320 if (StringRef(a->getValue()).endswith_lower(".def")) 321 add("-def:" + StringRef(a->getValue())); 322 else 323 add(prefix + StringRef(a->getValue())); 324 break; 325 case OPT_l: 326 add(prefix + searchLibrary(a->getValue(), searchPaths, isStatic)); 327 break; 328 case OPT_whole_archive: 329 prefix = "-wholearchive:"; 330 break; 331 case OPT_no_whole_archive: 332 prefix = ""; 333 break; 334 case OPT_Bstatic: 335 isStatic = true; 336 break; 337 case OPT_Bdynamic: 338 isStatic = false; 339 break; 340 } 341 } 342 343 if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH)) 344 outs() << llvm::join(linkArgs, " ") << "\n"; 345 346 if (args.hasArg(OPT__HASH_HASH_HASH)) 347 return true; 348 349 // Repack vector of strings to vector of const char pointers for coff::link. 350 std::vector<const char *> vec; 351 for (const std::string &s : linkArgs) 352 vec.push_back(s.c_str()); 353 return coff::link(vec, true); 354 } 355