xref: /llvm-project-15.0.7/lld/MinGW/Driver.cpp (revision 87aaa56b)
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 // MinGW is a GNU development environment for Windows. It consists of GNU
11 // tools such as GCC and GNU ld. Unlike Cygwin, there's no POSIX-compatible
12 // layer, as it aims to be a native development toolchain.
13 //
14 // lld/MinGW is a drop-in replacement for GNU ld/MinGW.
15 //
16 // Being a native development tool, a MinGW linker is not very different from
17 // Microsoft link.exe, so a MinGW linker can be implemented as a thin wrapper
18 // for lld/COFF. This driver takes Unix-ish command line options, translates
19 // them to Windows-ish ones, and then passes them to lld/COFF.
20 //
21 // When this driver calls the lld/COFF driver, it passes a hidden option
22 // "-lldmingw" along with other user-supplied options, to run the lld/COFF
23 // linker in "MinGW mode".
24 //
25 // There are subtle differences between MS link.exe and GNU ld/MinGW, and GNU
26 // ld/MinGW implements a few GNU-specific features. Such features are directly
27 // implemented in lld/COFF and enabled only when the linker is running in MinGW
28 // mode.
29 //
30 //===----------------------------------------------------------------------===//
31 
32 #include "lld/Common/Driver.h"
33 #include "lld/Common/ErrorHandler.h"
34 #include "llvm/ADT/ArrayRef.h"
35 #include "llvm/ADT/Optional.h"
36 #include "llvm/ADT/StringExtras.h"
37 #include "llvm/ADT/StringRef.h"
38 #include "llvm/Option/Arg.h"
39 #include "llvm/Option/ArgList.h"
40 #include "llvm/Option/Option.h"
41 #include "llvm/Support/CommandLine.h"
42 #include "llvm/Support/FileSystem.h"
43 #include "llvm/Support/Path.h"
44 
45 #if !defined(_MSC_VER) && !defined(__MINGW32__)
46 #include <unistd.h>
47 #endif
48 
49 using namespace lld;
50 using namespace llvm;
51 
52 // Create OptTable
53 enum {
54   OPT_INVALID = 0,
55 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
56 #include "Options.inc"
57 #undef OPTION
58 };
59 
60 // Create prefix string literals used in Options.td
61 #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
62 #include "Options.inc"
63 #undef PREFIX
64 
65 // Create table mapping all options defined in Options.td
66 static const opt::OptTable::Info InfoTable[] = {
67 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
68   {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
69    X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
70 #include "Options.inc"
71 #undef OPTION
72 };
73 
74 namespace {
75 class MinGWOptTable : public opt::OptTable {
76 public:
77   MinGWOptTable() : OptTable(InfoTable, false) {}
78   opt::InputArgList parse(ArrayRef<const char *> Argv);
79 };
80 } // namespace
81 
82 opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> Argv) {
83   unsigned MissingIndex;
84   unsigned MissingCount;
85 
86   SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
87   opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
88 
89   if (MissingCount)
90     fatal(StringRef(Args.getArgString(MissingIndex)) + ": missing argument");
91   for (auto *Arg : Args.filtered(OPT_UNKNOWN))
92     fatal("unknown argument: " + Arg->getSpelling());
93   if (!Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l))
94     fatal("no input files");
95   return Args;
96 }
97 
98 // Find a file by concatenating given paths.
99 static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {
100   SmallString<128> S;
101   sys::path::append(S, Path1, Path2);
102   if (sys::fs::exists(S))
103     return S.str().str();
104   return None;
105 }
106 
107 // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths.
108 static std::string
109 searchLibrary(StringRef Name, ArrayRef<StringRef> SearchPaths, bool BStatic) {
110   if (Name.startswith(":")) {
111     for (StringRef Dir : SearchPaths)
112       if (Optional<std::string> S = findFile(Dir, Name.substr(1)))
113         return *S;
114     fatal("unable to find library -l" + Name);
115   }
116 
117   for (StringRef Dir : SearchPaths) {
118     if (!BStatic)
119       if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a"))
120         return *S;
121     if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a"))
122       return *S;
123   }
124   fatal("unable to find library -l" + Name);
125 }
126 
127 // Convert Unix-ish command line arguments to Windows-ish ones and
128 // then call coff::link.
129 bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) {
130   MinGWOptTable Parser;
131   opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
132 
133   std::vector<std::string> LinkArgs;
134   auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); };
135 
136   Add("lld-link");
137   Add("-lldmingw");
138 
139   if (auto *A = Args.getLastArg(OPT_entry)) {
140     StringRef S = A->getValue();
141     if (Args.getLastArgValue(OPT_m) == "i386pe" && S.startswith("_"))
142       Add("-entry:" + S.substr(1));
143     else
144       Add("-entry:" + S);
145   }
146 
147   if (auto *A = Args.getLastArg(OPT_subs))
148     Add("-subsystem:" + StringRef(A->getValue()));
149   if (auto *A = Args.getLastArg(OPT_out_implib))
150     Add("-implib:" + StringRef(A->getValue()));
151   if (auto *A = Args.getLastArg(OPT_stack))
152     Add("-stack:" + StringRef(A->getValue()));
153   if (auto *A = Args.getLastArg(OPT_output_def))
154     Add("-output-def:" + StringRef(A->getValue()));
155   if (auto *A = Args.getLastArg(OPT_image_base))
156     Add("-base:" + StringRef(A->getValue()));
157   if (auto *A = Args.getLastArg(OPT_map))
158     Add("-lldmap:" + StringRef(A->getValue()));
159 
160   if (auto *A = Args.getLastArg(OPT_o))
161     Add("-out:" + StringRef(A->getValue()));
162   else if (Args.hasArg(OPT_shared))
163     Add("-out:a.dll");
164   else
165     Add("-out:a.exe");
166 
167   if (auto *A = Args.getLastArg(OPT_pdb)) {
168     Add("-debug");
169     Add("-pdb:" + StringRef(A->getValue()));
170   } else if (Args.hasArg(OPT_strip_debug)) {
171     Add("-debug:symtab");
172   } else if (!Args.hasArg(OPT_strip_all)) {
173     Add("-debug:dwarf");
174   }
175 
176   if (Args.hasArg(OPT_shared))
177     Add("-dll");
178   if (Args.hasArg(OPT_verbose))
179     Add("-verbose");
180   if (Args.hasArg(OPT_export_all_symbols))
181     Add("-export-all-symbols");
182   if (Args.hasArg(OPT_large_address_aware))
183     Add("-largeaddressaware");
184   if (Args.hasArg(OPT_kill_at))
185     Add("-kill-at");
186 
187   if (Args.getLastArgValue(OPT_m) != "thumb2pe" &&
188       Args.getLastArgValue(OPT_m) != "arm64pe" && !Args.hasArg(OPT_dynamicbase))
189     Add("-dynamicbase:no");
190 
191   if (Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false))
192     Add("-opt:ref");
193   else
194     Add("-opt:noref");
195 
196   if (auto *A = Args.getLastArg(OPT_icf)) {
197     StringRef S = A->getValue();
198     if (S == "all")
199       Add("-opt:icf");
200     else if (S == "safe" || S == "none")
201       Add("-opt:noicf");
202     else
203       fatal("unknown parameter: --icf=" + S);
204   } else {
205     Add("-opt:noicf");
206   }
207 
208   if (auto *A = Args.getLastArg(OPT_m)) {
209     StringRef S = A->getValue();
210     if (S == "i386pe")
211       Add("-machine:x86");
212     else if (S == "i386pep")
213       Add("-machine:x64");
214     else if (S == "thumb2pe")
215       Add("-machine:arm");
216     else if (S == "arm64pe")
217       Add("-machine:arm64");
218     else
219       fatal("unknown parameter: -m" + S);
220   }
221 
222   for (auto *A : Args.filtered(OPT_mllvm))
223     Add("-mllvm:" + StringRef(A->getValue()));
224 
225   for (auto *A : Args.filtered(OPT_Xlink))
226     Add(A->getValue());
227 
228   if (Args.getLastArgValue(OPT_m) == "i386pe")
229     Add("-alternatename:__image_base__=___ImageBase");
230   else
231     Add("-alternatename:__image_base__=__ImageBase");
232 
233   for (auto *A : Args.filtered(OPT_require_defined))
234     Add("-include:" + StringRef(A->getValue()));
235 
236   std::vector<StringRef> SearchPaths;
237   for (auto *A : Args.filtered(OPT_L)) {
238     SearchPaths.push_back(A->getValue());
239     Add("-libpath:" + StringRef(A->getValue()));
240   }
241 
242   StringRef Prefix = "";
243   bool Static = false;
244   for (auto *A : Args) {
245     switch (A->getOption().getUnaliasedOption().getID()) {
246     case OPT_INPUT:
247       if (StringRef(A->getValue()).endswith_lower(".def"))
248         Add("-def:" + StringRef(A->getValue()));
249       else
250         Add(Prefix + StringRef(A->getValue()));
251       break;
252     case OPT_l:
253       Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static));
254       break;
255     case OPT_whole_archive:
256       Prefix = "-wholearchive:";
257       break;
258     case OPT_no_whole_archive:
259       Prefix = "";
260       break;
261     case OPT_Bstatic:
262       Static = true;
263       break;
264     case OPT_Bdynamic:
265       Static = false;
266       break;
267     }
268   }
269 
270   if (Args.hasArg(OPT_verbose) || Args.hasArg(OPT__HASH_HASH_HASH))
271     outs() << llvm::join(LinkArgs, " ") << "\n";
272 
273   if (Args.hasArg(OPT__HASH_HASH_HASH))
274     return true;
275 
276   // Repack vector of strings to vector of const char pointers for coff::link.
277   std::vector<const char *> Vec;
278   for (const std::string &S : LinkArgs)
279     Vec.push_back(S.c_str());
280   return coff::link(Vec, true);
281 }
282