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 /// GNU ld style linker driver for COFF currently supporting mingw-w64. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "lld/Common/Driver.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/Optional.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/Option/Arg.h" 20 #include "llvm/Option/ArgList.h" 21 #include "llvm/Option/Option.h" 22 #include "llvm/Support/CommandLine.h" 23 #include "llvm/Support/FileSystem.h" 24 #include "llvm/Support/Path.h" 25 26 #if !defined(_MSC_VER) && !defined(__MINGW32__) 27 #include <unistd.h> 28 #endif 29 30 using namespace lld; 31 using namespace llvm; 32 33 LLVM_ATTRIBUTE_NORETURN static void error(const Twine &Msg) { 34 errs() << Msg << "\n"; 35 exit(1); 36 } 37 38 // Create OptTable 39 enum { 40 OPT_INVALID = 0, 41 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, 42 #include "Options.inc" 43 #undef OPTION 44 }; 45 46 // Create prefix string literals used in Options.td 47 #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; 48 #include "Options.inc" 49 #undef PREFIX 50 51 // Create table mapping all options defined in Options.td 52 static const opt::OptTable::Info InfoTable[] = { 53 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 54 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ 55 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 56 #include "Options.inc" 57 #undef OPTION 58 }; 59 60 namespace { 61 class MinGWOptTable : public opt::OptTable { 62 public: 63 MinGWOptTable() : OptTable(InfoTable, false) {} 64 opt::InputArgList parse(ArrayRef<const char *> Argv); 65 }; 66 } // namespace 67 68 opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> Argv) { 69 unsigned MissingIndex; 70 unsigned MissingCount; 71 72 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); 73 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); 74 75 if (MissingCount) 76 error(StringRef(Args.getArgString(MissingIndex)) + ": missing argument"); 77 for (auto *Arg : Args.filtered(OPT_UNKNOWN)) 78 error("unknown argument: " + Arg->getSpelling()); 79 if (!Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l)) 80 error("no input files"); 81 return Args; 82 } 83 84 // Find a file by concatenating given paths. 85 static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) { 86 SmallString<128> S; 87 sys::path::append(S, Path1, Path2); 88 if (sys::fs::exists(S)) 89 return S.str().str(); 90 return None; 91 } 92 93 // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. 94 static std::string 95 searchLibrary(StringRef Name, ArrayRef<StringRef> SearchPaths, bool BStatic) { 96 if (Name.startswith(":")) { 97 for (StringRef Dir : SearchPaths) 98 if (Optional<std::string> S = findFile(Dir, Name.substr(1))) 99 return *S; 100 error("unable to find library -l" + Name); 101 } 102 103 for (StringRef Dir : SearchPaths) { 104 if (!BStatic) 105 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a")) 106 return *S; 107 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) 108 return *S; 109 } 110 error("unable to find library -l" + Name); 111 } 112 113 // Convert Unix-ish command line arguments to Windows-ish ones and 114 // then call coff::link. 115 bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) { 116 MinGWOptTable Parser; 117 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); 118 119 std::vector<std::string> LinkArgs; 120 auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); }; 121 122 Add("lld-link"); 123 Add("-lldmingw"); 124 125 if (auto *A = Args.getLastArg(OPT_entry)) { 126 StringRef S = A->getValue(); 127 if (Args.getLastArgValue(OPT_m) == "i386pe" && S.startswith("_")) 128 Add("-entry:" + S.substr(1)); 129 else 130 Add("-entry:" + S); 131 } 132 133 if (auto *A = Args.getLastArg(OPT_subs)) 134 Add("-subsystem:" + StringRef(A->getValue())); 135 if (auto *A = Args.getLastArg(OPT_out_implib)) 136 Add("-implib:" + StringRef(A->getValue())); 137 if (auto *A = Args.getLastArg(OPT_stack)) 138 Add("-stack:" + StringRef(A->getValue())); 139 140 if (auto *A = Args.getLastArg(OPT_o)) 141 Add("-out:" + StringRef(A->getValue())); 142 else if (Args.hasArg(OPT_shared)) 143 Add("-out:a.dll"); 144 else 145 Add("-out:a.exe"); 146 147 if (Args.hasArg(OPT_shared)) 148 Add("-dll"); 149 if (Args.hasArg(OPT_verbose)) 150 Add("-verbose"); 151 152 if (auto *A = Args.getLastArg(OPT_m)) { 153 StringRef S = A->getValue(); 154 if (S == "i386pe") 155 Add("-machine:x86"); 156 else if (S == "i386pep") 157 Add("-machine:x64"); 158 else if (S == "thumb2pe") 159 Add("-machine:arm"); 160 else if (S == "arm64pe") 161 Add("-machine:arm64"); 162 else 163 error("unknown parameter: -m" + S); 164 } 165 166 for (auto *A : Args.filtered(OPT_mllvm)) 167 Add("-mllvm:" + StringRef(A->getValue())); 168 169 if (Args.getLastArgValue(OPT_m) == "i386pe") 170 Add("-alternatename:__image_base__=___ImageBase"); 171 else 172 Add("-alternatename:__image_base__=__ImageBase"); 173 174 std::vector<StringRef> SearchPaths; 175 for (auto *A : Args.filtered(OPT_L)) 176 SearchPaths.push_back(A->getValue()); 177 178 StringRef Prefix = ""; 179 bool Static = false; 180 for (auto *A : Args) { 181 switch (A->getOption().getUnaliasedOption().getID()) { 182 case OPT_INPUT: 183 if (StringRef(A->getValue()).endswith_lower(".def")) 184 Add("-def:" + StringRef(A->getValue())); 185 else 186 Add(Prefix + StringRef(A->getValue())); 187 break; 188 case OPT_l: 189 Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static)); 190 break; 191 case OPT_whole_archive: 192 Prefix = "-wholearchive:"; 193 break; 194 case OPT_no_whole_archive: 195 Prefix = ""; 196 break; 197 case OPT_Bstatic: 198 Static = true; 199 break; 200 case OPT_Bdynamic: 201 Static = false; 202 break; 203 } 204 } 205 206 if (Args.hasArg(OPT_verbose) || Args.hasArg(OPT__HASH_HASH_HASH)) 207 outs() << llvm::join(LinkArgs, " ") << "\n"; 208 209 if (Args.hasArg(OPT__HASH_HASH_HASH)) 210 return true; 211 212 // Repack vector of strings to vector of const char pointers for coff::link. 213 std::vector<const char *> Vec; 214 for (const std::string &S : LinkArgs) 215 Vec.push_back(S.c_str()); 216 return coff::link(Vec); 217 } 218