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 if (auto *A = Args.getLastArg(OPT_output_def)) 140 Add("-output-def:" + StringRef(A->getValue())); 141 142 if (auto *A = Args.getLastArg(OPT_o)) 143 Add("-out:" + StringRef(A->getValue())); 144 else if (Args.hasArg(OPT_shared)) 145 Add("-out:a.dll"); 146 else 147 Add("-out:a.exe"); 148 149 if (Args.hasArg(OPT_shared)) 150 Add("-dll"); 151 if (Args.hasArg(OPT_verbose)) 152 Add("-verbose"); 153 if (Args.hasArg(OPT_export_all_symbols)) 154 Add("-export-all-symbols"); 155 156 if (auto *A = Args.getLastArg(OPT_m)) { 157 StringRef S = A->getValue(); 158 if (S == "i386pe") 159 Add("-machine:x86"); 160 else if (S == "i386pep") 161 Add("-machine:x64"); 162 else if (S == "thumb2pe") 163 Add("-machine:arm"); 164 else if (S == "arm64pe") 165 Add("-machine:arm64"); 166 else 167 error("unknown parameter: -m" + S); 168 } 169 170 for (auto *A : Args.filtered(OPT_mllvm)) 171 Add("-mllvm:" + StringRef(A->getValue())); 172 173 if (Args.getLastArgValue(OPT_m) == "i386pe") 174 Add("-alternatename:__image_base__=___ImageBase"); 175 else 176 Add("-alternatename:__image_base__=__ImageBase"); 177 178 std::vector<StringRef> SearchPaths; 179 for (auto *A : Args.filtered(OPT_L)) 180 SearchPaths.push_back(A->getValue()); 181 182 StringRef Prefix = ""; 183 bool Static = false; 184 for (auto *A : Args) { 185 switch (A->getOption().getUnaliasedOption().getID()) { 186 case OPT_INPUT: 187 if (StringRef(A->getValue()).endswith_lower(".def")) 188 Add("-def:" + StringRef(A->getValue())); 189 else 190 Add(Prefix + StringRef(A->getValue())); 191 break; 192 case OPT_l: 193 Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static)); 194 break; 195 case OPT_whole_archive: 196 Prefix = "-wholearchive:"; 197 break; 198 case OPT_no_whole_archive: 199 Prefix = ""; 200 break; 201 case OPT_Bstatic: 202 Static = true; 203 break; 204 case OPT_Bdynamic: 205 Static = false; 206 break; 207 } 208 } 209 210 if (Args.hasArg(OPT_verbose) || Args.hasArg(OPT__HASH_HASH_HASH)) 211 outs() << llvm::join(LinkArgs, " ") << "\n"; 212 213 if (Args.hasArg(OPT__HASH_HASH_HASH)) 214 return true; 215 216 // Repack vector of strings to vector of const char pointers for coff::link. 217 std::vector<const char *> Vec; 218 for (const std::string &S : LinkArgs) 219 Vec.push_back(S.c_str()); 220 return coff::link(Vec); 221 } 222