Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 1 | //===- MinGW/Driver.cpp ---------------------------------------------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 | [diff] [blame] | 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 |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
Martin Storsjo | 5abe10a | 2019-01-05 10:43:59 | [diff] [blame] | 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 | // |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 29 | //===----------------------------------------------------------------------===// |
| 30 | |
Rui Ueyama | 6cb7141 | 2017-10-02 22:05:46 | [diff] [blame] | 31 | #include "lld/Common/Driver.h" |
Rui Ueyama | 338c4b2 | 2017-12-12 20:34:38 | [diff] [blame] | 32 | #include "lld/Common/ErrorHandler.h" |
Martin Storsjo | bb12396 | 2019-06-10 20:10:10 | [diff] [blame] | 33 | #include "lld/Common/Memory.h" |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 34 | #include "lld/Common/Version.h" |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 35 | #include "llvm/ADT/ArrayRef.h" |
| 36 | #include "llvm/ADT/Optional.h" |
Martin Storsjo | a79762a | 2017-09-11 20:43:39 | [diff] [blame] | 37 | #include "llvm/ADT/StringExtras.h" |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 38 | #include "llvm/ADT/StringRef.h" |
Martin Storsjo | bb12396 | 2019-06-10 20:10:10 | [diff] [blame] | 39 | #include "llvm/ADT/Triple.h" |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 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" |
Reid Kleckner | 213aea4 | 2020-03-11 22:39:28 | [diff] [blame] | 45 | #include "llvm/Support/Host.h" |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 46 | #include "llvm/Support/Path.h" |
| 47 | |
| 48 | #if !defined(_MSC_VER) && !defined(__MINGW32__) |
| 49 | #include <unistd.h> |
| 50 | #endif |
| 51 | |
| 52 | using namespace lld; |
| 53 | using namespace llvm; |
| 54 | |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 55 | // Create OptTable |
| 56 | enum { |
| 57 | OPT_INVALID = 0, |
| 58 | #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, |
| 59 | #include "Options.inc" |
| 60 | #undef OPTION |
| 61 | }; |
| 62 | |
| 63 | // Create prefix string literals used in Options.td |
Rui Ueyama | c16fd25 | 2017-09-11 22:04:13 | [diff] [blame] | 64 | #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 65 | #include "Options.inc" |
| 66 | #undef PREFIX |
| 67 | |
| 68 | // Create table mapping all options defined in Options.td |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 69 | static const opt::OptTable::Info infoTable[] = { |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 70 | #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ |
| 71 | {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ |
| 72 | X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, |
| 73 | #include "Options.inc" |
| 74 | #undef OPTION |
| 75 | }; |
| 76 | |
Rui Ueyama | c16fd25 | 2017-09-11 22:04:13 | [diff] [blame] | 77 | namespace { |
Rui Ueyama | 4474796 | 2017-09-11 22:04:25 | [diff] [blame] | 78 | class MinGWOptTable : public opt::OptTable { |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 79 | public: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 80 | MinGWOptTable() : OptTable(infoTable, false) {} |
| 81 | opt::InputArgList parse(ArrayRef<const char *> argv); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 82 | }; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 83 | } // namespace |
| 84 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 85 | static void printHelp(const char *argv0) { |
Fangrui Song | f1e2d58 | 2021-06-24 21:47:03 | [diff] [blame] | 86 | MinGWOptTable().printHelp( |
Rui Ueyama | b11386f | 2019-11-15 05:06:57 | [diff] [blame] | 87 | lld::outs(), (std::string(argv0) + " [options] file...").c_str(), "lld", |
Martin Storsjo | 9ae0d22 | 2019-05-17 11:07:38 | [diff] [blame] | 88 | false /*ShowHidden*/, true /*ShowAllAliases*/); |
Rui Ueyama | b11386f | 2019-11-15 05:06:57 | [diff] [blame] | 89 | lld::outs() << "\n"; |
Martin Storsjo | 9ae0d22 | 2019-05-17 11:07:38 | [diff] [blame] | 90 | } |
| 91 | |
Martin Storsjo | bb12396 | 2019-06-10 20:10:10 | [diff] [blame] | 92 | static cl::TokenizerCallback getQuotingStyle() { |
| 93 | if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32) |
| 94 | return cl::TokenizeWindowsCommandLine; |
| 95 | return cl::TokenizeGNUCommandLine; |
| 96 | } |
| 97 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 98 | opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> argv) { |
| 99 | unsigned missingIndex; |
| 100 | unsigned missingCount; |
Rui Ueyama | d2da71f | 2017-09-11 22:04:37 | [diff] [blame] | 101 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 102 | SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size()); |
Alexandre Ganea | 83d59e0 | 2022-01-20 19:53:18 | [diff] [blame] | 103 | cl::ExpandResponseFiles(saver(), getQuotingStyle(), vec); |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 104 | opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); |
Rui Ueyama | d2da71f | 2017-09-11 22:04:37 | [diff] [blame] | 105 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 106 | if (missingCount) |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame] | 107 | error(StringRef(args.getArgString(missingIndex)) + ": missing argument"); |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 108 | for (auto *arg : args.filtered(OPT_UNKNOWN)) |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame] | 109 | error("unknown argument: " + arg->getAsString(args)); |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 110 | return args; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | // Find a file by concatenating given paths. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 114 | static Optional<std::string> findFile(StringRef path1, const Twine &path2) { |
| 115 | SmallString<128> s; |
| 116 | sys::path::append(s, path1, path2); |
| 117 | if (sys::fs::exists(s)) |
Jonas Devlieghere | 3e24242 | 2020-01-30 05:30:21 | [diff] [blame] | 118 | return std::string(s); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 119 | return None; |
| 120 | } |
| 121 | |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 122 | // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 123 | static std::string |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 124 | searchLibrary(StringRef name, ArrayRef<StringRef> searchPaths, bool bStatic) { |
| 125 | if (name.startswith(":")) { |
| 126 | for (StringRef dir : searchPaths) |
| 127 | if (Optional<std::string> s = findFile(dir, name.substr(1))) |
| 128 | return *s; |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 129 | error("unable to find library -l" + name); |
| 130 | return ""; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 131 | } |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 132 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 133 | for (StringRef dir : searchPaths) { |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 134 | if (!bStatic) { |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 135 | if (Optional<std::string> s = findFile(dir, "lib" + name + ".dll.a")) |
| 136 | return *s; |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 137 | if (Optional<std::string> s = findFile(dir, name + ".dll.a")) |
| 138 | return *s; |
| 139 | } |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 140 | if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) |
| 141 | return *s; |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 142 | if (!bStatic) { |
| 143 | if (Optional<std::string> s = findFile(dir, name + ".lib")) |
| 144 | return *s; |
Martin Storsjö | c09e5e5 | 2021-06-17 12:57:20 | [diff] [blame] | 145 | if (Optional<std::string> s = findFile(dir, "lib" + name + ".dll")) |
| 146 | return *s; |
| 147 | if (Optional<std::string> s = findFile(dir, name + ".dll")) |
| 148 | return *s; |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 149 | } |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 150 | } |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 151 | error("unable to find library -l" + name); |
| 152 | return ""; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 153 | } |
| 154 | |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 155 | // Convert Unix-ish command line arguments to Windows-ish ones and |
| 156 | // then call coff::link. |
Alexandre Ganea | 83d59e0 | 2022-01-20 19:53:18 | [diff] [blame] | 157 | bool mingw::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, |
| 158 | llvm::raw_ostream &stderrOS, bool exitEarly, |
| 159 | bool disableOutput) { |
| 160 | auto *ctx = new CommonLinkerContext; |
| 161 | ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput); |
James Y Knight | d3fec7f | 2019-11-20 15:08:18 | [diff] [blame] | 162 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 163 | MinGWOptTable parser; |
| 164 | opt::InputArgList args = parser.parse(argsArr.slice(1)); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 165 | |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame] | 166 | if (errorCount()) |
| 167 | return false; |
| 168 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 169 | if (args.hasArg(OPT_help)) { |
| 170 | printHelp(argsArr[0]); |
Martin Storsjo | 9ae0d22 | 2019-05-17 11:07:38 | [diff] [blame] | 171 | return true; |
| 172 | } |
| 173 | |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 174 | // A note about "compatible with GNU linkers" message: this is a hack for |
| 175 | // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and |
| 176 | // still the newest version in March 2017) or earlier to recognize LLD as |
| 177 | // a GNU compatible linker. As long as an output for the -v option |
| 178 | // contains "GNU" or "with BFD", they recognize us as GNU-compatible. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 179 | if (args.hasArg(OPT_v) || args.hasArg(OPT_version)) |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 180 | message(getLLDVersion() + " (compatible with GNU linkers)"); |
| 181 | |
| 182 | // The behavior of -v or --version is a bit strange, but this is |
| 183 | // needed for compatibility with GNU linkers. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 184 | if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 185 | return true; |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 186 | if (args.hasArg(OPT_version)) |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 187 | return true; |
| 188 | |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame] | 189 | if (!args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) { |
| 190 | error("no input files"); |
| 191 | return false; |
| 192 | } |
Martin Storsjo | 9ae0d22 | 2019-05-17 11:07:38 | [diff] [blame] | 193 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 194 | std::vector<std::string> linkArgs; |
| 195 | auto add = [&](const Twine &s) { linkArgs.push_back(s.str()); }; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 196 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 197 | add("lld-link"); |
| 198 | add("-lldmingw"); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 199 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 200 | if (auto *a = args.getLastArg(OPT_entry)) { |
| 201 | StringRef s = a->getValue(); |
| 202 | if (args.getLastArgValue(OPT_m) == "i386pe" && s.startswith("_")) |
| 203 | add("-entry:" + s.substr(1)); |
Martin Storsjo | 6d8dace | 2017-09-12 19:23:54 | [diff] [blame] | 204 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 205 | add("-entry:" + s); |
Martin Storsjo | 6d8dace | 2017-09-12 19:23:54 | [diff] [blame] | 206 | } |
| 207 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 208 | if (args.hasArg(OPT_major_os_version, OPT_minor_os_version, |
Martin Storsjo | 6f047ae | 2019-06-14 17:50:35 | [diff] [blame] | 209 | OPT_major_subsystem_version, OPT_minor_subsystem_version)) { |
Martin Storsjö | bc8f3b4 | 2020-10-04 08:52:36 | [diff] [blame] | 210 | StringRef majOSVer = args.getLastArgValue(OPT_major_os_version, "6"); |
| 211 | StringRef minOSVer = args.getLastArgValue(OPT_minor_os_version, "0"); |
Martin Storsjö | 61e2f9f | 2020-10-04 14:59:33 | [diff] [blame] | 212 | StringRef majSubSysVer = "6"; |
| 213 | StringRef minSubSysVer = "0"; |
| 214 | StringRef subSysName = "default"; |
| 215 | StringRef subSysVer; |
| 216 | // Iterate over --{major,minor}-subsystem-version and --subsystem, and pick |
| 217 | // the version number components from the last one of them that specifies |
| 218 | // a version. |
| 219 | for (auto *a : args.filtered(OPT_major_subsystem_version, |
| 220 | OPT_minor_subsystem_version, OPT_subs)) { |
| 221 | switch (a->getOption().getID()) { |
| 222 | case OPT_major_subsystem_version: |
| 223 | majSubSysVer = a->getValue(); |
| 224 | break; |
| 225 | case OPT_minor_subsystem_version: |
| 226 | minSubSysVer = a->getValue(); |
| 227 | break; |
| 228 | case OPT_subs: |
| 229 | std::tie(subSysName, subSysVer) = StringRef(a->getValue()).split(':'); |
| 230 | if (!subSysVer.empty()) { |
| 231 | if (subSysVer.contains('.')) |
| 232 | std::tie(majSubSysVer, minSubSysVer) = subSysVer.split('.'); |
| 233 | else |
| 234 | majSubSysVer = subSysVer; |
| 235 | } |
| 236 | break; |
| 237 | } |
| 238 | } |
Martin Storsjö | bc8f3b4 | 2020-10-04 08:52:36 | [diff] [blame] | 239 | add("-osversion:" + majOSVer + "." + minOSVer); |
Martin Storsjö | 61e2f9f | 2020-10-04 14:59:33 | [diff] [blame] | 240 | add("-subsystem:" + subSysName + "," + majSubSysVer + "." + minSubSysVer); |
| 241 | } else if (args.hasArg(OPT_subs)) { |
| 242 | StringRef subSys = args.getLastArgValue(OPT_subs, "default"); |
| 243 | StringRef subSysName, subSysVer; |
| 244 | std::tie(subSysName, subSysVer) = subSys.split(':'); |
| 245 | StringRef sep = subSysVer.empty() ? "" : ","; |
| 246 | add("-subsystem:" + subSysName + sep + subSysVer); |
Martin Storsjo | 6f047ae | 2019-06-14 17:50:35 | [diff] [blame] | 247 | } |
| 248 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 249 | if (auto *a = args.getLastArg(OPT_out_implib)) |
| 250 | add("-implib:" + StringRef(a->getValue())); |
| 251 | if (auto *a = args.getLastArg(OPT_stack)) |
| 252 | add("-stack:" + StringRef(a->getValue())); |
| 253 | if (auto *a = args.getLastArg(OPT_output_def)) |
| 254 | add("-output-def:" + StringRef(a->getValue())); |
| 255 | if (auto *a = args.getLastArg(OPT_image_base)) |
| 256 | add("-base:" + StringRef(a->getValue())); |
| 257 | if (auto *a = args.getLastArg(OPT_map)) |
| 258 | add("-lldmap:" + StringRef(a->getValue())); |
Rui Ueyama | e4758a5 | 2019-10-04 07:27:45 | [diff] [blame] | 259 | if (auto *a = args.getLastArg(OPT_reproduce)) |
| 260 | add("-reproduce:" + StringRef(a->getValue())); |
Tobias Hieta | f794808b | 2020-05-24 09:29:16 | [diff] [blame] | 261 | if (auto *a = args.getLastArg(OPT_thinlto_cache_dir)) |
| 262 | add("-lldltocache:" + StringRef(a->getValue())); |
Martin Storsjö | 92f7bd3 | 2020-07-13 21:12:13 | [diff] [blame] | 263 | if (auto *a = args.getLastArg(OPT_file_alignment)) |
| 264 | add("-filealign:" + StringRef(a->getValue())); |
| 265 | if (auto *a = args.getLastArg(OPT_section_alignment)) |
| 266 | add("-align:" + StringRef(a->getValue())); |
Mateusz Mikuła | 460830a | 2022-01-29 21:36:50 | [diff] [blame] | 267 | if (auto *a = args.getLastArg(OPT_heap)) |
| 268 | add("-heap:" + StringRef(a->getValue())); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 269 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 270 | if (auto *a = args.getLastArg(OPT_o)) |
| 271 | add("-out:" + StringRef(a->getValue())); |
| 272 | else if (args.hasArg(OPT_shared)) |
| 273 | add("-out:a.dll"); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 274 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 275 | add("-out:a.exe"); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 276 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 277 | if (auto *a = args.getLastArg(OPT_pdb)) { |
| 278 | add("-debug"); |
| 279 | StringRef v = a->getValue(); |
| 280 | if (!v.empty()) |
| 281 | add("-pdb:" + v); |
| 282 | } else if (args.hasArg(OPT_strip_debug)) { |
| 283 | add("-debug:symtab"); |
| 284 | } else if (!args.hasArg(OPT_strip_all)) { |
| 285 | add("-debug:dwarf"); |
Martin Storsjo | b7d5011 | 2018-05-15 06:34:18 | [diff] [blame] | 286 | } |
| 287 | |
Mateusz Mikuła | 84306ef | 2021-05-17 07:39:59 | [diff] [blame] | 288 | if (args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false)) |
| 289 | add("-WX"); |
| 290 | else |
| 291 | add("-WX:no"); |
| 292 | |
Martin Storsjö | ce211c5 | 2021-06-17 18:51:37 | [diff] [blame] | 293 | if (args.hasFlag(OPT_enable_stdcall_fixup, OPT_disable_stdcall_fixup, false)) |
| 294 | add("-stdcall-fixup"); |
| 295 | else if (args.hasArg(OPT_disable_stdcall_fixup)) |
| 296 | add("-stdcall-fixup:no"); |
| 297 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 298 | if (args.hasArg(OPT_shared)) |
| 299 | add("-dll"); |
| 300 | if (args.hasArg(OPT_verbose)) |
| 301 | add("-verbose"); |
| 302 | if (args.hasArg(OPT_exclude_all_symbols)) |
| 303 | add("-exclude-all-symbols"); |
| 304 | if (args.hasArg(OPT_export_all_symbols)) |
| 305 | add("-export-all-symbols"); |
| 306 | if (args.hasArg(OPT_large_address_aware)) |
| 307 | add("-largeaddressaware"); |
| 308 | if (args.hasArg(OPT_kill_at)) |
| 309 | add("-kill-at"); |
| 310 | if (args.hasArg(OPT_appcontainer)) |
| 311 | add("-appcontainer"); |
Martin Storsjö | f8340c8 | 2021-08-11 20:41:24 | [diff] [blame] | 312 | if (args.hasFlag(OPT_no_seh, OPT_disable_no_seh, false)) |
Martin Storsjö | 745eb02 | 2020-07-27 20:44:41 | [diff] [blame] | 313 | add("-noseh"); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 314 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 315 | if (args.getLastArgValue(OPT_m) != "thumb2pe" && |
Martin Storsjö | e72403f | 2020-08-26 13:02:52 | [diff] [blame] | 316 | args.getLastArgValue(OPT_m) != "arm64pe" && |
Martin Storsjö | f8340c8 | 2021-08-11 20:41:24 | [diff] [blame] | 317 | args.hasFlag(OPT_disable_dynamicbase, OPT_dynamicbase, false)) |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 318 | add("-dynamicbase:no"); |
Martin Storsjö | f8340c8 | 2021-08-11 20:41:24 | [diff] [blame] | 319 | if (args.hasFlag(OPT_disable_high_entropy_va, OPT_high_entropy_va, false)) |
| 320 | add("-highentropyva:no"); |
| 321 | if (args.hasFlag(OPT_disable_nxcompat, OPT_nxcompat, false)) |
| 322 | add("-nxcompat:no"); |
| 323 | if (args.hasFlag(OPT_disable_tsaware, OPT_tsaware, false)) |
| 324 | add("-tsaware:no"); |
Martin Storsjo | 094d8c0 | 2017-11-15 08:18:11 | [diff] [blame] | 325 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 326 | if (args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false)) |
| 327 | add("-timestamp:0"); |
Martin Storsjo | 537a718 | 2019-02-05 08:16:06 | [diff] [blame] | 328 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 329 | if (args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) |
| 330 | add("-opt:ref"); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 331 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 332 | add("-opt:noref"); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 333 | |
Martin Storsjö | 248e345 | 2020-12-30 21:02:01 | [diff] [blame] | 334 | if (args.hasFlag(OPT_demangle, OPT_no_demangle, true)) |
| 335 | add("-demangle"); |
| 336 | else |
| 337 | add("-demangle:no"); |
| 338 | |
Martin Storsjö | 7f0e6c3 | 2020-04-25 21:49:44 | [diff] [blame] | 339 | if (args.hasFlag(OPT_enable_auto_import, OPT_disable_auto_import, true)) |
| 340 | add("-auto-import"); |
| 341 | else |
| 342 | add("-auto-import:no"); |
| 343 | if (args.hasFlag(OPT_enable_runtime_pseudo_reloc, |
| 344 | OPT_disable_runtime_pseudo_reloc, true)) |
| 345 | add("-runtime-pseudo-reloc"); |
| 346 | else |
| 347 | add("-runtime-pseudo-reloc:no"); |
| 348 | |
Mateusz Mikuła | c82078b | 2020-08-26 06:25:52 | [diff] [blame] | 349 | if (args.hasFlag(OPT_allow_multiple_definition, |
| 350 | OPT_no_allow_multiple_definition, false)) |
| 351 | add("-force:multiple"); |
| 352 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 353 | if (auto *a = args.getLastArg(OPT_icf)) { |
| 354 | StringRef s = a->getValue(); |
| 355 | if (s == "all") |
| 356 | add("-opt:icf"); |
| 357 | else if (s == "safe" || s == "none") |
| 358 | add("-opt:noicf"); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 359 | else |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame] | 360 | error("unknown parameter: --icf=" + s); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 361 | } else { |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 362 | add("-opt:noicf"); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 363 | } |
| 364 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 365 | if (auto *a = args.getLastArg(OPT_m)) { |
| 366 | StringRef s = a->getValue(); |
| 367 | if (s == "i386pe") |
| 368 | add("-machine:x86"); |
| 369 | else if (s == "i386pep") |
| 370 | add("-machine:x64"); |
| 371 | else if (s == "thumb2pe") |
| 372 | add("-machine:arm"); |
| 373 | else if (s == "arm64pe") |
| 374 | add("-machine:arm64"); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 375 | else |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame] | 376 | error("unknown parameter: -m" + s); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 377 | } |
| 378 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 379 | for (auto *a : args.filtered(OPT_mllvm)) |
| 380 | add("-mllvm:" + StringRef(a->getValue())); |
Martell Malone | 0d17638 | 2017-09-11 21:36:37 | [diff] [blame] | 381 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 382 | for (auto *a : args.filtered(OPT_Xlink)) |
| 383 | add(a->getValue()); |
Martin Storsjo | 107b548 | 2017-11-03 07:18:37 | [diff] [blame] | 384 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 385 | if (args.getLastArgValue(OPT_m) == "i386pe") |
| 386 | add("-alternatename:__image_base__=___ImageBase"); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 387 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 388 | add("-alternatename:__image_base__=__ImageBase"); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 389 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 390 | for (auto *a : args.filtered(OPT_require_defined)) |
| 391 | add("-include:" + StringRef(a->getValue())); |
| 392 | for (auto *a : args.filtered(OPT_undefined)) |
| 393 | add("-includeoptional:" + StringRef(a->getValue())); |
Martin Storsjo | c92b356 | 2019-08-05 11:57:06 | [diff] [blame] | 394 | for (auto *a : args.filtered(OPT_delayload)) |
| 395 | add("-delayload:" + StringRef(a->getValue())); |
Martin Storsjö | 3785a41 | 2020-10-06 10:54:49 | [diff] [blame] | 396 | for (auto *a : args.filtered(OPT_wrap)) |
| 397 | add("-wrap:" + StringRef(a->getValue())); |
Martin Storsjo | db62913 | 2018-09-10 17:41:40 | [diff] [blame] | 398 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 399 | std::vector<StringRef> searchPaths; |
| 400 | for (auto *a : args.filtered(OPT_L)) { |
| 401 | searchPaths.push_back(a->getValue()); |
| 402 | add("-libpath:" + StringRef(a->getValue())); |
Martin Storsjo | 803b37a | 2018-10-10 09:00:03 | [diff] [blame] | 403 | } |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 404 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 405 | StringRef prefix = ""; |
| 406 | bool isStatic = false; |
| 407 | for (auto *a : args) { |
| 408 | switch (a->getOption().getID()) { |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 409 | case OPT_INPUT: |
Martin Storsjö | 3c6f8ca | 2021-06-24 08:06:35 | [diff] [blame] | 410 | if (StringRef(a->getValue()).endswith_insensitive(".def")) |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 411 | add("-def:" + StringRef(a->getValue())); |
Martin Storsjo | 064b0fa | 2017-09-13 07:28:13 | [diff] [blame] | 412 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 413 | add(prefix + StringRef(a->getValue())); |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 414 | break; |
| 415 | case OPT_l: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 416 | add(prefix + searchLibrary(a->getValue(), searchPaths, isStatic)); |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 417 | break; |
| 418 | case OPT_whole_archive: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 419 | prefix = "-wholearchive:"; |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 420 | break; |
| 421 | case OPT_no_whole_archive: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 422 | prefix = ""; |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 423 | break; |
Martin Storsjo | 2ba37d4 | 2017-09-13 19:29:44 | [diff] [blame] | 424 | case OPT_Bstatic: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 425 | isStatic = true; |
Martin Storsjo | 2ba37d4 | 2017-09-13 19:29:44 | [diff] [blame] | 426 | break; |
| 427 | case OPT_Bdynamic: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 428 | isStatic = false; |
Martin Storsjo | 2ba37d4 | 2017-09-13 19:29:44 | [diff] [blame] | 429 | break; |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 430 | } |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 431 | } |
| 432 | |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 433 | if (errorCount()) |
| 434 | return false; |
| 435 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 436 | if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH)) |
Martin Storsjö | fdf54f5 | 2021-06-18 11:33:28 | [diff] [blame] | 437 | lld::errs() << llvm::join(linkArgs, " ") << "\n"; |
Martin Storsjo | a79762a | 2017-09-11 20:43:39 | [diff] [blame] | 438 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 439 | if (args.hasArg(OPT__HASH_HASH_HASH)) |
Martin Storsjo | a79762a | 2017-09-11 20:43:39 | [diff] [blame] | 440 | return true; |
| 441 | |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 442 | // Repack vector of strings to vector of const char pointers for coff::link. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 443 | std::vector<const char *> vec; |
| 444 | for (const std::string &s : linkArgs) |
| 445 | vec.push_back(s.c_str()); |
Martin Storsjö | 1c8bb62 | 2021-06-18 11:29:55 | [diff] [blame] | 446 | // Pass the actual binary name, to make error messages be printed with |
| 447 | // the right prefix. |
| 448 | vec[0] = argsArr[0]; |
Alexandre Ganea | 83d59e0 | 2022-01-20 19:53:18 | [diff] [blame] | 449 | |
| 450 | // The context will be re-created in the COFF driver. |
| 451 | lld::CommonLinkerContext::destroy(); |
| 452 | |
| 453 | return coff::link(vec, stdoutOS, stderrOS, exitEarly, disableOutput); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 454 | } |