blob: 4c296da35d6679c42344c296ac2963b01275d485 [file] [log] [blame]
Rui Ueyama411c63602015-05-28 19:09:301//===- Driver.cpp ---------------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:563// 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
Rui Ueyama411c63602015-05-28 19:09:306//
7//===----------------------------------------------------------------------===//
8
Rui Ueyama411c63602015-05-28 19:09:309#include "Driver.h"
Amy Huang6f7483b2021-09-16 23:48:2610#include "COFFLinkerContext.h"
Rui Ueyama1d99ab32016-09-15 22:24:5111#include "Config.h"
Nico Weber1dc21232019-06-12 11:32:4312#include "DebugTypes.h"
Sam Cleggf187c4d2018-02-20 22:09:5913#include "ICF.h"
Rui Ueyama411c63602015-05-28 19:09:3014#include "InputFiles.h"
Sam Cleggf187c4d2018-02-20 22:09:5915#include "MarkLive.h"
Martin Storsjoe1f894d2017-10-19 19:49:3816#include "MinGW.h"
Rui Ueyama411c63602015-05-28 19:09:3017#include "SymbolTable.h"
Rui Ueyama685c41c2015-08-05 23:43:5318#include "Symbols.h"
Rui Ueyama411c63602015-05-28 19:09:3019#include "Writer.h"
Rui Ueyama57175aa2018-01-27 00:34:4620#include "lld/Common/Args.h"
Fangrui Song6b9a80d2022-12-28 18:46:4521#include "lld/Common/CommonLinkerContext.h"
Rui Ueyama3f851702017-10-02 21:00:4122#include "lld/Common/Driver.h"
Rui Ueyama7fd99fc2019-03-11 16:30:5523#include "lld/Common/Filesystem.h"
Zachary Turner727f1532018-01-17 19:16:2624#include "lld/Common/Timer.h"
Rui Ueyamaa4cf97b2017-10-23 14:57:5325#include "lld/Common/Version.h"
serge-sans-paillef06d4872022-03-09 21:27:3526#include "llvm/ADT/IntrusiveRefCntPtr.h"
Saleem Abdulrasoola2cca7e2016-08-08 22:02:4427#include "llvm/ADT/StringSwitch.h"
Zachary Turner264b5d92017-06-07 03:48:5628#include "llvm/BinaryFormat/Magic.h"
Arthur Eubanksfed75652020-12-08 18:21:1729#include "llvm/Config/llvm-config.h"
Steven Wudd63b9f2019-09-16 18:49:5730#include "llvm/LTO/LTO.h"
Rui Ueyamae1bf1362017-03-16 21:19:3631#include "llvm/Object/ArchiveWriter.h"
Reid Kleckner146eb7a2017-06-02 17:53:0632#include "llvm/Object/COFFImportFile.h"
Rui Ueyama411c63602015-05-28 19:09:3033#include "llvm/Option/Arg.h"
34#include "llvm/Option/ArgList.h"
35#include "llvm/Option/Option.h"
Zequan Wu763671f2020-07-21 20:46:1136#include "llvm/Support/BinaryStreamReader.h"
Reid Kleckner4c1a1d32019-11-14 23:15:4837#include "llvm/Support/CommandLine.h"
Rui Ueyama411c63602015-05-28 19:09:3038#include "llvm/Support/Debug.h"
Peter Collingbourneab038022018-08-23 17:44:4239#include "llvm/Support/LEB128.h"
Rui Ueyamae6a33e12019-08-07 10:16:2140#include "llvm/Support/MathExtras.h"
Reid Kleckner932f0272020-05-05 03:03:1941#include "llvm/Support/Parallel.h"
Rui Ueyama411c63602015-05-28 19:09:3042#include "llvm/Support/Path.h"
Rui Ueyama54b71da2015-05-31 19:17:1243#include "llvm/Support/Process.h"
Rui Ueyama7f1f9122017-01-06 02:33:5344#include "llvm/Support/TarWriter.h"
Peter Collingbourne60c16162015-06-01 20:10:1045#include "llvm/Support/TargetSelect.h"
Nikita Popov49ae2dc2024-06-20 15:41:3546#include "llvm/Support/TimeProfiler.h"
serge-sans-paillef06d4872022-03-09 21:27:3547#include "llvm/Support/VirtualFileSystem.h"
Rui Ueyama411c63602015-05-28 19:09:3048#include "llvm/Support/raw_ostream.h"
Archibald Elliott62c7f032023-02-07 12:21:5149#include "llvm/TargetParser/Triple.h"
Peter Collingbournec6f07c42017-05-13 22:06:4650#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
Rui Ueyama2bf6a122015-06-14 21:50:5051#include <algorithm>
Peter Collingbourne6ee0b4e2016-12-15 04:02:2352#include <future>
Sam Cleggf187c4d2018-02-20 22:09:5953#include <memory>
Kazu Hiratafd8d0b02022-11-27 04:53:2654#include <optional>
Ivan Tadeu Ferreira Antunes Filho73fd9d32023-04-04 16:57:5355#include <tuple>
Peter Collingbourne6ee0b4e2016-12-15 04:02:2356
Fangrui Song982575fd2024-12-04 04:51:5057using namespace lld;
58using namespace lld::coff;
Rui Ueyama411c63602015-05-28 19:09:3059using namespace llvm;
Reid Kleckner146eb7a2017-06-02 17:53:0660using namespace llvm::object;
Rui Ueyama84936e02015-07-07 23:39:1861using namespace llvm::COFF;
Nico Webere6d1f262021-02-22 19:29:5562using namespace llvm::sys;
Rui Ueyama411c63602015-05-28 19:09:3063
Fangrui Song982575fd2024-12-04 04:51:5064COFFSyncStream::COFFSyncStream(COFFLinkerContext &ctx, DiagLevel level)
65 : SyncStream(ctx.e, level), ctx(ctx) {}
66
67COFFSyncStream coff::Log(COFFLinkerContext &ctx) {
68 return {ctx, DiagLevel::Log};
69}
70COFFSyncStream coff::Msg(COFFLinkerContext &ctx) {
71 return {ctx, DiagLevel::Msg};
72}
73COFFSyncStream coff::Warn(COFFLinkerContext &ctx) {
74 return {ctx, DiagLevel::Warn};
75}
76COFFSyncStream coff::Err(COFFLinkerContext &ctx) {
77 return {ctx, DiagLevel::Err};
78}
79COFFSyncStream coff::Fatal(COFFLinkerContext &ctx) {
80 return {ctx, DiagLevel::Fatal};
81}
82uint64_t coff::errCount(COFFLinkerContext &ctx) { return ctx.e.errorCount; }
83
Nico Weber7c266412022-08-08 15:32:2684namespace lld::coff {
Rui Ueyama411c63602015-05-28 19:09:3085
Alexandre Ganea83d59e02022-01-20 19:53:1886bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
87 llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
Alexandre Ganea6f2e92c2023-06-19 11:32:3488 // This driver-specific context will be freed later by unsafeLldMain().
Alexandre Ganea83d59e02022-01-20 19:53:1889 auto *ctx = new COFFLinkerContext;
James Y Knightd3fec7f2019-11-20 15:08:1890
Alexandre Ganea83d59e02022-01-20 19:53:1891 ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
92 ctx->e.logName = args::getFilenameWithoutExe(args[0]);
93 ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now"
94 " (use /errorlimit:0 to see all errors)";
Alexandre Ganeaf2efb572020-09-24 19:00:4395
Amy Huang5a58b192023-01-10 04:37:2896 ctx->driver.linkerMain(args);
Rui Ueyama6f4e2552017-10-23 20:03:3297
Fangrui Song982575fd2024-12-04 04:51:5098 return errCount(*ctx) == 0;
Rui Ueyamaa9cbbf82015-05-31 19:17:0999}
Rui Ueyama411c63602015-05-28 19:09:30100
Bob Haarman5011b832019-07-11 18:48:58101// Parse options of the form "old;new".
Fangrui Song8d225f12024-12-06 03:44:26102static std::pair<StringRef, StringRef>
103getOldNewOptions(COFFLinkerContext &ctx, opt::InputArgList &args, unsigned id) {
Bob Haarman5011b832019-07-11 18:48:58104 auto *arg = args.getLastArg(id);
105 if (!arg)
106 return {"", ""};
107
108 StringRef s = arg->getValue();
109 std::pair<StringRef, StringRef> ret = s.split(';');
110 if (ret.second.empty())
Fangrui Song8d225f12024-12-06 03:44:26111 Err(ctx) << arg->getSpelling() << " expects 'old;new' format, but got "
112 << s;
Bob Haarman5011b832019-07-11 18:48:58113 return ret;
114}
115
Ivan Tadeu Ferreira Antunes Filho73fd9d32023-04-04 16:57:53116// Parse options of the form "old;new[;extra]".
117static std::tuple<StringRef, StringRef, StringRef>
Fangrui Song8d225f12024-12-06 03:44:26118getOldNewOptionsExtra(COFFLinkerContext &ctx, opt::InputArgList &args,
119 unsigned id) {
120 auto [oldDir, second] = getOldNewOptions(ctx, args, id);
Ivan Tadeu Ferreira Antunes Filho73fd9d32023-04-04 16:57:53121 auto [newDir, extraDir] = second.split(';');
122 return {oldDir, newDir, extraDir};
123}
124
Rui Ueyamaf95ed692019-11-13 04:53:15125// Drop directory components and replace extension with
126// ".exe", ".dll" or ".sys".
Amy Huang5a58b192023-01-10 04:37:28127static std::string getOutputPath(StringRef path, bool isDll, bool isDriver) {
Rui Ueyamaf95ed692019-11-13 04:53:15128 StringRef ext = ".exe";
Amy Huang5a58b192023-01-10 04:37:28129 if (isDll)
Rui Ueyamaf95ed692019-11-13 04:53:15130 ext = ".dll";
Amy Huang5a58b192023-01-10 04:37:28131 else if (isDriver)
Rui Ueyamaf95ed692019-11-13 04:53:15132 ext = ".sys";
133
134 return (sys::path::stem(path) + ext).str();
Rui Ueyama411c63602015-05-28 19:09:30135}
136
Martin Storsjocdf126e2019-04-15 10:57:44137// Returns true if S matches /crtend.?\.o$/.
Rui Ueyama136d27a2019-07-11 05:40:30138static bool isCrtend(StringRef s) {
Kazu Hirata9ed46fb2024-09-23 03:45:25139 if (!s.consume_back(".o"))
Martin Storsjocdf126e2019-04-15 10:57:44140 return false;
Fangrui Song8d85c962023-06-05 21:36:19141 if (s.ends_with("crtend"))
Martin Storsjocdf126e2019-04-15 10:57:44142 return true;
Fangrui Song8d85c962023-06-05 21:36:19143 return !s.empty() && s.drop_back().ends_with("crtend");
Martin Storsjocdf126e2019-04-15 10:57:44144}
145
Peter Collingbourne6ee0b4e2016-12-15 04:02:23146// ErrorOr is not default constructible, so it cannot be used as the type
147// parameter of a future.
148// FIXME: We could open the file in createFutureForFile and avoid needing to
149// return an error here, but for the moment that would cost us a file descriptor
150// (a limited resource on Windows) for the duration that the future is pending.
Rui Ueyama68b9f452019-04-01 00:11:24151using MBErrPair = std::pair<std::unique_ptr<MemoryBuffer>, std::error_code>;
Peter Collingbourne6ee0b4e2016-12-15 04:02:23152
153// Create a std::future that opens and maps a file using the best strategy for
154// the host platform.
Rui Ueyama136d27a2019-07-11 05:40:30155static std::future<MBErrPair> createFutureForFile(std::string path) {
Jeremy Drake7a7da692021-07-07 18:45:00156#if _WIN64
Peter Collingbourne6ee0b4e2016-12-15 04:02:23157 // On Windows, file I/O is relatively slow so it is best to do this
Jeremy Drake7a7da692021-07-07 18:45:00158 // asynchronously. But 32-bit has issues with potentially launching tons
159 // of threads
Rui Ueyama77565f72019-07-11 06:56:44160 auto strategy = std::launch::async;
Peter Collingbourne6ee0b4e2016-12-15 04:02:23161#else
Rui Ueyama136d27a2019-07-11 05:40:30162 auto strategy = std::launch::deferred;
Peter Collingbourne6ee0b4e2016-12-15 04:02:23163#endif
Rui Ueyama136d27a2019-07-11 05:40:30164 return std::async(strategy, [=]() {
Abhina Sreeskantharajanc83cd8f2021-03-25 13:47:25165 auto mbOrErr = MemoryBuffer::getFile(path, /*IsText=*/false,
166 /*RequiresNullTerminator=*/false);
Rui Ueyama136d27a2019-07-11 05:40:30167 if (!mbOrErr)
168 return MBErrPair{nullptr, mbOrErr.getError()};
169 return MBErrPair{std::move(*mbOrErr), std::error_code()};
Peter Collingbourne6ee0b4e2016-12-15 04:02:23170 });
171}
172
Amy Huang5a58b192023-01-10 04:37:28173llvm::Triple::ArchType LinkerDriver::getArch() {
Jacek Cabanff565842024-04-04 12:25:54174 return getMachineArchType(ctx.config.machine);
Peter Kastingc5fb05f2022-02-16 14:20:03175}
176
Jacek Caban1bd5f342025-01-16 11:55:12177std::vector<Chunk *> LinkerDriver::getChunks() const {
178 std::vector<Chunk *> res;
179 for (ObjFile *file : ctx.objFileInstances) {
180 ArrayRef<Chunk *> v = file->getChunks();
181 res.insert(res.end(), v.begin(), v.end());
182 }
183 return res;
184}
185
Jacek Caban84352252025-01-01 18:42:49186static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) {
187 if (mt == IMAGE_FILE_MACHINE_UNKNOWN)
188 return true;
189 switch (ctx.config.machine) {
190 case ARM64:
191 return mt == ARM64 || mt == ARM64X;
192 case ARM64EC:
193 return isArm64EC(mt) || mt == AMD64;
194 case ARM64X:
195 return isAnyArm64(mt) || mt == AMD64;
196 case IMAGE_FILE_MACHINE_UNKNOWN:
197 return true;
198 default:
199 return ctx.config.machine == mt;
200 }
201}
202
203void LinkerDriver::addFile(InputFile *file) {
204 Log(ctx) << "Reading " << toString(file);
205 if (file->lazy) {
206 if (auto *f = dyn_cast<BitcodeFile>(file))
207 f->parseLazy();
208 else
209 cast<ObjFile>(file)->parseLazy();
210 } else {
211 file->parse();
212 if (auto *f = dyn_cast<ObjFile>(file)) {
213 ctx.objFileInstances.push_back(f);
214 } else if (auto *f = dyn_cast<BitcodeFile>(file)) {
215 if (ltoCompilationDone) {
216 Err(ctx) << "LTO object file " << toString(file)
217 << " linked in after "
218 "doing LTO compilation.";
219 }
Jacek Cabanb068f2f2025-01-17 10:36:12220 f->symtab.bitcodeFileInstances.push_back(f);
Jacek Caban84352252025-01-01 18:42:49221 } else if (auto *f = dyn_cast<ImportFile>(file)) {
222 ctx.importFileInstances.push_back(f);
223 }
224 }
225
226 MachineTypes mt = file->getMachineType();
227 // The ARM64EC target must be explicitly specified and cannot be inferred.
228 if (mt == ARM64EC &&
229 (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN ||
230 (ctx.config.machineInferred &&
231 (ctx.config.machine == ARM64 || ctx.config.machine == AMD64)))) {
232 Err(ctx) << toString(file)
233 << ": machine type arm64ec is ambiguous and cannot be "
234 "inferred, use /machine:arm64ec or /machine:arm64x";
235 return;
236 }
237 if (!compatibleMachineType(ctx, mt)) {
238 Err(ctx) << toString(file) << ": machine type " << machineToStr(mt)
239 << " conflicts with " << machineToStr(ctx.config.machine);
240 return;
241 }
242 if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN &&
243 mt != IMAGE_FILE_MACHINE_UNKNOWN) {
244 ctx.config.machineInferred = true;
245 setMachine(mt);
246 }
247
248 parseDirectives(file);
249}
250
Rui Ueyama136d27a2019-07-11 05:40:30251MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> mb) {
252 MemoryBufferRef mbref = *mb;
253 make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take ownership
Peter Collingbourne6ee0b4e2016-12-15 04:02:23254
Amy Huang5a58b192023-01-10 04:37:28255 if (ctx.driver.tar)
256 ctx.driver.tar->append(relativeToRoot(mbref.getBufferIdentifier()),
257 mbref.getBuffer());
Rui Ueyama136d27a2019-07-11 05:40:30258 return mbref;
Rui Ueyama2bf6a122015-06-14 21:50:50259}
Rui Ueyama711cd2d2015-05-31 21:17:10260
Rui Ueyama136d27a2019-07-11 05:40:30261void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
Bob Haarman7dc5e7a02019-09-03 20:32:16262 bool wholeArchive, bool lazy) {
Rui Ueyama136d27a2019-07-11 05:40:30263 StringRef filename = mb->getBufferIdentifier();
Rui Ueyamacdd5fb52018-03-01 23:11:30264
Rui Ueyama136d27a2019-07-11 05:40:30265 MemoryBufferRef mbref = takeBuffer(std::move(mb));
Peter Collingbournefeee2102016-07-26 02:00:42266
Rui Ueyama711cd2d2015-05-31 21:17:10267 // File type is detected by contents, not by file extension.
Rui Ueyama136d27a2019-07-11 05:40:30268 switch (identify_magic(mbref.getBuffer())) {
Peter Collingbourne9362ac62017-10-16 23:15:04269 case file_magic::windows_resource:
Rui Ueyama136d27a2019-07-11 05:40:30270 resources.push_back(mbref);
Peter Collingbourne9362ac62017-10-16 23:15:04271 break;
Peter Collingbourne9362ac62017-10-16 23:15:04272 case file_magic::archive:
Rui Ueyama136d27a2019-07-11 05:40:30273 if (wholeArchive) {
274 std::unique_ptr<Archive> file =
275 CHECK(Archive::create(mbref), filename + ": failed to parse archive");
Martin Storsjo90b43882019-08-01 18:47:27276 Archive *archive = file.get();
277 make<std::unique_ptr<Archive>>(std::move(file)); // take ownership
Martin Storsjo8278ba52017-09-13 07:28:03278
Rui Ueyama89efb032019-09-10 11:50:26279 int memberIndex = 0;
Fangrui Song8b844de2024-12-06 04:18:01280 for (MemoryBufferRef m : getArchiveMembers(ctx, archive))
Rui Ueyama89efb032019-09-10 11:50:26281 addArchiveBuffer(m, "<whole-archive>", filename, memberIndex++);
Martin Storsjo8278ba52017-09-13 07:28:03282 return;
283 }
Jacek Caban84352252025-01-01 18:42:49284 addFile(make<ArchiveFile>(ctx, mbref));
Peter Collingbourne9362ac62017-10-16 23:15:04285 break;
Peter Collingbourne9362ac62017-10-16 23:15:04286 case file_magic::bitcode:
Jacek Cabanb068f2f2025-01-17 10:36:12287 addFile(BitcodeFile::create(ctx, mbref, "", 0, lazy));
Peter Collingbourne9362ac62017-10-16 23:15:04288 break;
Rui Ueyamacdd5fb52018-03-01 23:11:30289 case file_magic::coff_object:
290 case file_magic::coff_import_library:
Jacek Caban84352252025-01-01 18:42:49291 addFile(ObjFile::create(ctx, mbref, lazy));
Peter Collingbourne9362ac62017-10-16 23:15:04292 break;
Alexandre Ganea9c78db62019-06-03 12:39:47293 case file_magic::pdb:
Jacek Caban84352252025-01-01 18:42:49294 addFile(make<PDBInputFile>(ctx, mbref));
Alexandre Ganea9c78db62019-06-03 12:39:47295 break;
Rui Ueyamacdd5fb52018-03-01 23:11:30296 case file_magic::coff_cl_gl_object:
Fangrui Song982575fd2024-12-04 04:51:50297 Err(ctx) << filename
298 << ": is not a native COFF file. Recompile without /GL";
Rui Ueyamacdd5fb52018-03-01 23:11:30299 break;
300 case file_magic::pecoff_executable:
Amy Huang5a58b192023-01-10 04:37:28301 if (ctx.config.mingw) {
Jacek Caban84352252025-01-01 18:42:49302 addFile(make<DLLFile>(ctx.symtab, mbref));
Martin Storsjöa9ff1ce2021-06-16 13:59:46303 break;
304 }
Kazu Hirataed1539c2023-05-16 17:12:42305 if (filename.ends_with_insensitive(".dll")) {
Fangrui Song8d225f12024-12-06 03:44:26306 Err(ctx) << filename
307 << ": bad file type. Did you specify a DLL instead of an "
308 "import library?";
Rui Ueyamacdd5fb52018-03-01 23:11:30309 break;
310 }
Fangrui Songec04e452022-08-07 00:02:35311 [[fallthrough]];
Rui Ueyamacdd5fb52018-03-01 23:11:30312 default:
Fangrui Song8d225f12024-12-06 03:44:26313 Err(ctx) << mbref.getBufferIdentifier() << ": unknown file type";
Rui Ueyamacdd5fb52018-03-01 23:11:30314 break;
Peter Collingbourne9362ac62017-10-16 23:15:04315 }
Peter Collingbourne6ee0b4e2016-12-15 04:02:23316}
317
Bob Haarman7dc5e7a02019-09-03 20:32:16318void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {
Benjamin Krameradcd0262020-01-28 19:23:46319 auto future = std::make_shared<std::future<MBErrPair>>(
320 createFutureForFile(std::string(path)));
321 std::string pathStr = std::string(path);
Peter Collingbourne6ee0b4e2016-12-15 04:02:23322 enqueueTask([=]() {
Alexandre Ganea356139b2023-10-06 02:33:58323 llvm::TimeTraceScope timeScope("File: ", path);
Arthur Eubanksc8ea6692023-05-31 15:52:21324 auto [mb, ec] = future->get();
325 if (ec) {
326 // Retry reading the file (synchronously) now that we may have added
327 // winsysroot search paths from SymbolTable::addFile().
328 // Retrying synchronously is important for keeping the order of inputs
329 // consistent.
330 // This makes it so that if the user passes something in the winsysroot
331 // before something we can find with an architecture, we won't find the
332 // winsysroot file.
Arthur Eubanks5f8f3102023-06-06 18:11:52333 if (std::optional<StringRef> retryPath = findFileIfNew(pathStr)) {
Arthur Eubanksc8ea6692023-05-31 15:52:21334 auto retryMb = MemoryBuffer::getFile(*retryPath, /*IsText=*/false,
335 /*RequiresNullTerminator=*/false);
336 ec = retryMb.getError();
337 if (!ec)
338 mb = std::move(*retryMb);
Arthur Eubanksec1998c2023-06-05 21:32:55339 } else {
340 // We've already handled this file.
341 return;
Arthur Eubanksc8ea6692023-05-31 15:52:21342 }
343 }
344 if (ec) {
345 std::string msg = "could not open '" + pathStr + "': " + ec.message();
Nico Weber9b2830b2019-05-23 17:58:33346 // Check if the filename is a typo for an option flag. OptTable thinks
347 // that all args that are not known options and that start with / are
348 // filenames, but e.g. `/nodefaultlibs` is more likely a typo for
349 // the option `/nodefaultlib` than a reference to a file in the root
350 // directory.
Rui Ueyama136d27a2019-07-11 05:40:30351 std::string nearest;
Amy Huang5a58b192023-01-10 04:37:28352 if (ctx.optTable.findNearest(pathStr, nearest) > 1)
Fangrui Song8d225f12024-12-06 03:44:26353 Err(ctx) << msg;
Nico Weber9b2830b2019-05-23 17:58:33354 else
Fangrui Song8d225f12024-12-06 03:44:26355 Err(ctx) << msg << "; did you mean '" << nearest << "'";
Nico Weber9b2830b2019-05-23 17:58:33356 } else
Arthur Eubanksc8ea6692023-05-31 15:52:21357 ctx.driver.addBuffer(std::move(mb), wholeArchive, lazy);
Peter Collingbourne6ee0b4e2016-12-15 04:02:23358 });
Peter Collingbourne6ee0b4e2016-12-15 04:02:23359}
360
Rui Ueyama136d27a2019-07-11 05:40:30361void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,
362 StringRef parentName,
363 uint64_t offsetInArchive) {
364 file_magic magic = identify_magic(mb.getBuffer());
365 if (magic == file_magic::coff_import_library) {
Amy Huang6f7483b2021-09-16 23:48:26366 InputFile *imp = make<ImportFile>(ctx, mb);
Rui Ueyama136d27a2019-07-11 05:40:30367 imp->parentName = parentName;
Jacek Caban84352252025-01-01 18:42:49368 addFile(imp);
Peter Collingbourne6ee0b4e2016-12-15 04:02:23369 return;
370 }
371
Rui Ueyama136d27a2019-07-11 05:40:30372 InputFile *obj;
373 if (magic == file_magic::coff_object) {
Jacek Caban9c8214f2024-12-17 18:26:13374 obj = ObjFile::create(ctx, mb);
Rui Ueyama136d27a2019-07-11 05:40:30375 } else if (magic == file_magic::bitcode) {
Jacek Cabanb068f2f2025-01-17 10:36:12376 obj = BitcodeFile::create(ctx, mb, parentName, offsetInArchive,
377 /*lazy=*/false);
Pengxuan Zhengc951edb2022-08-09 00:49:08378 } else if (magic == file_magic::coff_cl_gl_object) {
Fangrui Song8d225f12024-12-06 03:44:26379 Err(ctx) << mb.getBufferIdentifier()
380 << ": is not a native COFF file. Recompile without /GL?";
Pengxuan Zhengc951edb2022-08-09 00:49:08381 return;
Bob Haarmanac8f7fc2017-04-05 00:43:54382 } else {
Fangrui Song8d225f12024-12-06 03:44:26383 Err(ctx) << "unknown file type: " << mb.getBufferIdentifier();
Bob Haarmanac8f7fc2017-04-05 00:43:54384 return;
385 }
Peter Collingbourne6ee0b4e2016-12-15 04:02:23386
Rui Ueyama136d27a2019-07-11 05:40:30387 obj->parentName = parentName;
Jacek Caban84352252025-01-01 18:42:49388 addFile(obj);
Fangrui Song982575fd2024-12-04 04:51:50389 Log(ctx) << "Loaded " << obj << " for " << symName;
Peter Collingbourne6ee0b4e2016-12-15 04:02:23390}
391
Rui Ueyama136d27a2019-07-11 05:40:30392void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
Nico Webercb2c5002019-07-19 13:29:10393 const Archive::Symbol &sym,
Rui Ueyama136d27a2019-07-11 05:40:30394 StringRef parentName) {
Bob Haarman3edf63c2019-02-08 21:59:35395
Nico Webercb2c5002019-07-19 13:29:10396 auto reportBufferError = [=](Error &&e, StringRef childName) {
Fangrui Song982575fd2024-12-04 04:51:50397 Fatal(ctx) << "could not get the buffer for the member defining symbol "
398 << &sym << ": " << parentName << "(" << childName
399 << "): " << std::move(e);
Bob Haarman3edf63c2019-02-08 21:59:35400 };
401
Rui Ueyama136d27a2019-07-11 05:40:30402 if (!c.getParent()->isThin()) {
403 uint64_t offsetInArchive = c.getChildOffset();
404 Expected<MemoryBufferRef> mbOrErr = c.getMemoryBufferRef();
405 if (!mbOrErr)
406 reportBufferError(mbOrErr.takeError(), check(c.getFullName()));
407 MemoryBufferRef mb = mbOrErr.get();
Bob Haarman8b1ec792019-04-15 19:48:32408 enqueueTask([=]() {
Alexandre Ganea356139b2023-10-06 02:33:58409 llvm::TimeTraceScope timeScope("Archive: ", mb.getBufferIdentifier());
Amy Huang5a58b192023-01-10 04:37:28410 ctx.driver.addArchiveBuffer(mb, toCOFFString(ctx, sym), parentName,
411 offsetInArchive);
Bob Haarman8b1ec792019-04-15 19:48:32412 });
Peter Collingbourne6ee0b4e2016-12-15 04:02:23413 return;
414 }
415
Amy Huang5a58b192023-01-10 04:37:28416 std::string childName =
417 CHECK(c.getFullName(),
418 "could not get the filename for the member defining symbol " +
419 toCOFFString(ctx, sym));
Matheus Izvekova5e280b2023-09-21 11:16:11420 auto future =
421 std::make_shared<std::future<MBErrPair>>(createFutureForFile(childName));
Peter Collingbourne6ee0b4e2016-12-15 04:02:23422 enqueueTask([=]() {
Rui Ueyama136d27a2019-07-11 05:40:30423 auto mbOrErr = future->get();
424 if (mbOrErr.second)
425 reportBufferError(errorCodeToError(mbOrErr.second), childName);
Alexandre Ganea356139b2023-10-06 02:33:58426 llvm::TimeTraceScope timeScope("Archive: ",
427 mbOrErr.first->getBufferIdentifier());
Amy Huang227d8592019-09-12 22:04:56428 // Pass empty string as archive name so that the original filename is
429 // used as the buffer identifier.
Amy Huang5a58b192023-01-10 04:37:28430 ctx.driver.addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)),
431 toCOFFString(ctx, sym), "",
432 /*OffsetInArchive=*/0);
Peter Collingbourne6ee0b4e2016-12-15 04:02:23433 });
Rui Ueyama411c63602015-05-28 19:09:30434}
435
Amy Huang5a58b192023-01-10 04:37:28436bool LinkerDriver::isDecorated(StringRef sym) {
Fangrui Song8d85c962023-06-05 21:36:19437 return sym.starts_with("@") || sym.contains("@@") || sym.starts_with("?") ||
Amy Huang5a58b192023-01-10 04:37:28438 (!ctx.config.mingw && sym.contains('@'));
Rui Ueyamaf10a3202015-08-31 08:43:21439}
440
Rui Ueyama411c63602015-05-28 19:09:30441// Parses .drectve section contents and returns a list of files
442// specified by /defaultlib.
Rui Ueyama136d27a2019-07-11 05:40:30443void LinkerDriver::parseDirectives(InputFile *file) {
444 StringRef s = file->getDirectives();
445 if (s.empty())
Alexandre Ganead8ec8102019-03-06 20:18:38446 return;
447
Fangrui Song982575fd2024-12-04 04:51:50448 Log(ctx) << "Directives: " << file << ": " << s;
Alexandre Ganead8ec8102019-03-06 20:18:38449
Amy Huang5a58b192023-01-10 04:37:28450 ArgParser parser(ctx);
Nico Webera05cbb82017-09-05 23:46:45451 // .drectve is always tokenized using Windows shell rules.
Rui Ueyama5fa0d6e2018-01-09 20:36:42452 // /EXPORT: option can appear too many times, processing in fastpath.
Reid Kleckner01b5f522020-04-25 00:26:17453 ParsedDirectives directives = parser.parseDirectives(s);
Rui Ueyama5fa0d6e2018-01-09 20:36:42454
Reid Kleckner01b5f522020-04-25 00:26:17455 for (StringRef e : directives.exports) {
Rui Ueyama5fa0d6e2018-01-09 20:36:42456 // If a common header file contains dllexported function
457 // declarations, many object files may end up with having the
458 // same /EXPORT options. In order to save cost of parsing them,
459 // we dedup them first.
Jacek Caban455b3d62025-01-21 09:41:15460 if (!file->symtab.directivesExports.insert(e).second)
Rui Ueyama5fa0d6e2018-01-09 20:36:42461 continue;
462
Rui Ueyama136d27a2019-07-11 05:40:30463 Export exp = parseExport(e);
Amy Huang5a58b192023-01-10 04:37:28464 if (ctx.config.machine == I386 && ctx.config.mingw) {
Rui Ueyama136d27a2019-07-11 05:40:30465 if (!isDecorated(exp.name))
Alexandre Ganea83d59e02022-01-20 19:53:18466 exp.name = saver().save("_" + exp.name);
Rui Ueyama136d27a2019-07-11 05:40:30467 if (!exp.extName.empty() && !isDecorated(exp.extName))
Alexandre Ganea83d59e02022-01-20 19:53:18468 exp.extName = saver().save("_" + exp.extName);
Rui Ueyama5fa0d6e2018-01-09 20:36:42469 }
Alexandre Ganeaadcdc9c2023-06-13 19:12:55470 exp.source = ExportSource::Directives;
Jacek Caban455b3d62025-01-21 09:41:15471 file->symtab.exports.push_back(exp);
Rui Ueyama5fa0d6e2018-01-09 20:36:42472 }
Rui Ueyama411c63602015-05-28 19:09:30473
Reid Kleckner01b5f522020-04-25 00:26:17474 // Handle /include: in bulk.
475 for (StringRef inc : directives.includes)
Jacek Caban251ef3f2025-01-13 22:16:57476 file->symtab.addGCRoot(inc);
Reid Kleckner01b5f522020-04-25 00:26:17477
Martin Storsjö5d513ef2022-07-17 21:11:37478 // Handle /exclude-symbols: in bulk.
479 for (StringRef e : directives.excludes) {
480 SmallVector<StringRef, 2> vec;
481 e.split(vec, ',');
482 for (StringRef sym : vec)
Jacek Cabanf22af592025-01-15 14:21:06483 excludedSymbols.insert(file->symtab.mangle(sym));
Martin Storsjö5d513ef2022-07-17 21:11:37484 }
485
Nico Weber400a1de2021-08-24 14:19:21486 // https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-160
Reid Kleckner01b5f522020-04-25 00:26:17487 for (auto *arg : directives.args) {
Rui Ueyama136d27a2019-07-11 05:40:30488 switch (arg->getOption().getID()) {
Martin Storsjod2752aa2017-08-14 19:07:27489 case OPT_aligncomm:
Jacek Cabanf2473bc2025-03-03 21:48:20490 file->symtab.parseAligncomm(arg->getValue());
Martin Storsjod2752aa2017-08-14 19:07:27491 break;
Rui Ueyama562daa82015-06-18 21:50:38492 case OPT_alternatename:
Jacek Caban8616c872025-02-21 11:52:28493 file->symtab.parseAlternateName(arg->getValue());
Rui Ueyama562daa82015-06-18 21:50:38494 break;
495 case OPT_defaultlib:
Arthur Eubanks5f8f3102023-06-06 18:11:52496 if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))
Bob Haarman7dc5e7a02019-09-03 20:32:16497 enqueuePath(*path, false, false);
Rui Ueyama562daa82015-06-18 21:50:38498 break;
Rui Ueyama215286f2017-11-29 20:46:13499 case OPT_entry:
Martin Storsjöcb248f82024-06-24 17:02:39500 if (!arg->getValue()[0])
Fangrui Song982575fd2024-12-04 04:51:50501 Fatal(ctx) << "missing entry point symbol name";
Jacek Caband0049472025-01-16 11:53:48502 ctx.forEachSymtab([&](SymbolTable &symtab) {
503 symtab.entry = symtab.addGCRoot(symtab.mangle(arg->getValue()), true);
504 });
Rui Ueyama215286f2017-11-29 20:46:13505 break;
Rui Ueyama562daa82015-06-18 21:50:38506 case OPT_failifmismatch:
Rui Ueyama136d27a2019-07-11 05:40:30507 checkFailIfMismatch(arg->getValue(), file);
Rui Ueyama562daa82015-06-18 21:50:38508 break;
Rui Ueyama08d5e182015-06-18 23:20:11509 case OPT_incl:
Jacek Caban251ef3f2025-01-13 22:16:57510 file->symtab.addGCRoot(arg->getValue());
Rui Ueyama08d5e182015-06-18 23:20:11511 break;
Nico Weber400a1de2021-08-24 14:19:21512 case OPT_manifestdependency:
Amy Huang5a58b192023-01-10 04:37:28513 ctx.config.manifestDependencies.insert(arg->getValue());
Nico Weber400a1de2021-08-24 14:19:21514 break;
Rui Ueyamace86c992015-06-18 23:22:39515 case OPT_merge:
Rui Ueyama136d27a2019-07-11 05:40:30516 parseMerge(arg->getValue());
Rui Ueyamace86c992015-06-18 23:22:39517 break;
518 case OPT_nodefaultlib:
Arthur Eubanks5f8f3102023-06-06 18:11:52519 ctx.config.noDefaultLibs.insert(findLib(arg->getValue()).lower());
Rui Ueyamace86c992015-06-18 23:22:39520 break;
Qfrost3f558532023-01-02 09:20:15521 case OPT_release:
Amy Huang5a58b192023-01-10 04:37:28522 ctx.config.writeCheckSum = true;
Qfrost3f558532023-01-02 09:20:15523 break;
Rui Ueyama440138c2016-06-20 03:39:39524 case OPT_section:
Rui Ueyama136d27a2019-07-11 05:40:30525 parseSection(arg->getValue());
Rui Ueyama440138c2016-06-20 03:39:39526 break;
Alex Reinking7ac3fcc2021-05-05 22:54:17527 case OPT_stack:
Amy Huang5a58b192023-01-10 04:37:28528 parseNumbers(arg->getValue(), &ctx.config.stackReserve,
529 &ctx.config.stackCommit);
Alex Reinking7ac3fcc2021-05-05 22:54:17530 break;
Martin Storsjö45c4c542020-10-03 22:29:45531 case OPT_subsystem: {
532 bool gotVersion = false;
Amy Huang5a58b192023-01-10 04:37:28533 parseSubsystem(arg->getValue(), &ctx.config.subsystem,
534 &ctx.config.majorSubsystemVersion,
535 &ctx.config.minorSubsystemVersion, &gotVersion);
Martin Storsjö45c4c542020-10-03 22:29:45536 if (gotVersion) {
Amy Huang5a58b192023-01-10 04:37:28537 ctx.config.majorOSVersion = ctx.config.majorSubsystemVersion;
538 ctx.config.minorOSVersion = ctx.config.minorSubsystemVersion;
Martin Storsjö45c4c542020-10-03 22:29:45539 }
Rui Ueyama215286f2017-11-29 20:46:13540 break;
Martin Storsjö45c4c542020-10-03 22:29:45541 }
Nico Webere7a67bf2019-07-09 13:30:03542 // Only add flags here that link.exe accepts in
543 // `#pragma comment(linker, "/flag")`-generated sections.
Rui Ueyama3c4737d2015-08-11 16:46:08544 case OPT_editandcontinue:
Rui Ueyama31e66e32015-09-03 16:20:47545 case OPT_guardsym:
Rui Ueyama432383172015-07-29 21:01:15546 case OPT_throwingnew:
Alvin Wong8fa0cfe2023-04-23 15:58:24547 case OPT_inferasanlibs:
548 case OPT_inferasanlibs_no:
Rui Ueyama46682632015-07-29 20:29:15549 break;
Rui Ueyama562daa82015-06-18 21:50:38550 default:
Fangrui Song8d225f12024-12-06 03:44:26551 Err(ctx) << arg->getSpelling() << " is not allowed in .drectve ("
552 << toString(file) << ")";
Rui Ueyamad7c2f582015-05-31 21:04:56553 }
554 }
Rui Ueyama411c63602015-05-28 19:09:30555}
556
Rui Ueyama54b71da2015-05-31 19:17:12557// Find file from search paths. You can omit ".obj", this function takes
558// care of that. Note that the returned path is not guaranteed to exist.
Arthur Eubanks5f8f3102023-06-06 18:11:52559StringRef LinkerDriver::findFile(StringRef filename) {
Amy Huang5a58b192023-01-10 04:37:28560 auto getFilename = [this](StringRef filename) -> StringRef {
561 if (ctx.config.vfs)
562 if (auto statOrErr = ctx.config.vfs->status(filename))
Alex Brachetfd9962e2022-07-11 21:31:01563 return saver().save(statOrErr->getName());
564 return filename;
565 };
566
Tobias Hietab6c2f102023-07-14 07:40:35567 if (sys::path::is_absolute(filename))
Alex Brachetfd9962e2022-07-11 21:31:01568 return getFilename(filename);
Rui Ueyama136d27a2019-07-11 05:40:30569 bool hasExt = filename.contains('.');
570 for (StringRef dir : searchPaths) {
571 SmallString<128> path = dir;
572 sys::path::append(path, filename);
Alex Brachetfd9962e2022-07-11 21:31:01573 path = SmallString<128>{getFilename(path.str())};
Rui Ueyama136d27a2019-07-11 05:40:30574 if (sys::fs::exists(path.str()))
Alexandre Ganea83d59e02022-01-20 19:53:18575 return saver().save(path.str());
Rui Ueyama136d27a2019-07-11 05:40:30576 if (!hasExt) {
577 path.append(".obj");
Alex Brachetfd9962e2022-07-11 21:31:01578 path = SmallString<128>{getFilename(path.str())};
Rui Ueyama136d27a2019-07-11 05:40:30579 if (sys::fs::exists(path.str()))
Alexandre Ganea83d59e02022-01-20 19:53:18580 return saver().save(path.str());
Rui Ueyama54b71da2015-05-31 19:17:12581 }
582 }
Rui Ueyama136d27a2019-07-11 05:40:30583 return filename;
Rui Ueyama54b71da2015-05-31 19:17:12584}
585
Fangrui Song9da7aee2022-11-28 00:39:40586static std::optional<sys::fs::UniqueID> getUniqueID(StringRef path) {
Rui Ueyama136d27a2019-07-11 05:40:30587 sys::fs::UniqueID ret;
588 if (sys::fs::getUniqueID(path, ret))
Fangrui Song9da7aee2022-11-28 00:39:40589 return std::nullopt;
Rui Ueyama136d27a2019-07-11 05:40:30590 return ret;
Rui Ueyama4eed6cc2018-06-12 21:47:31591}
592
Rui Ueyamad21b00b2015-05-31 19:17:14593// Resolves a file path. This never returns the same path
Kazu Hiratad6684f22022-12-11 01:04:56594// (in that case, it returns std::nullopt).
Arthur Eubanks5f8f3102023-06-06 18:11:52595std::optional<StringRef> LinkerDriver::findFileIfNew(StringRef filename) {
596 StringRef path = findFile(filename);
Rui Ueyama4eed6cc2018-06-12 21:47:31597
Fangrui Song9da7aee2022-11-28 00:39:40598 if (std::optional<sys::fs::UniqueID> id = getUniqueID(path)) {
Rui Ueyama136d27a2019-07-11 05:40:30599 bool seen = !visitedFiles.insert(*id).second;
600 if (seen)
Fangrui Song9da7aee2022-11-28 00:39:40601 return std::nullopt;
Rui Ueyama4eed6cc2018-06-12 21:47:31602 }
603
Kazu Hirataed1539c2023-05-16 17:12:42604 if (path.ends_with_insensitive(".lib"))
Pengxuan Zheng9db61c32022-06-14 02:22:14605 visitedLibs.insert(std::string(sys::path::filename(path).lower()));
Rui Ueyama136d27a2019-07-11 05:40:30606 return path;
Rui Ueyama54b71da2015-05-31 19:17:12607}
608
Martin Storsjo33d43ff2018-10-10 09:00:10609// MinGW specific. If an embedded directive specified to link to
610// foo.lib, but it isn't found, try libfoo.a instead.
Arthur Eubanks5f8f3102023-06-06 18:11:52611StringRef LinkerDriver::findLibMinGW(StringRef filename) {
Rui Ueyama136d27a2019-07-11 05:40:30612 if (filename.contains('/') || filename.contains('\\'))
613 return filename;
Martin Storsjo33d43ff2018-10-10 09:00:10614
Rui Ueyama136d27a2019-07-11 05:40:30615 SmallString<128> s = filename;
616 sys::path::replace_extension(s, ".a");
Alexandre Ganea83d59e02022-01-20 19:53:18617 StringRef libName = saver().save("lib" + s.str());
Arthur Eubanks5f8f3102023-06-06 18:11:52618 return findFile(libName);
Martin Storsjo33d43ff2018-10-10 09:00:10619}
620
Rui Ueyamad21b00b2015-05-31 19:17:14621// Find library file from search path.
Arthur Eubanks5f8f3102023-06-06 18:11:52622StringRef LinkerDriver::findLib(StringRef filename) {
Rui Ueyamad21b00b2015-05-31 19:17:14623 // Add ".lib" to Filename if that has no file extension.
Rui Ueyama136d27a2019-07-11 05:40:30624 bool hasExt = filename.contains('.');
625 if (!hasExt)
Alexandre Ganea83d59e02022-01-20 19:53:18626 filename = saver().save(filename + ".lib");
Arthur Eubanks5f8f3102023-06-06 18:11:52627 StringRef ret = findFile(filename);
Martin Storsjo33d43ff2018-10-10 09:00:10628 // For MinGW, if the find above didn't turn up anything, try
629 // looking for a MinGW formatted library name.
Amy Huang5a58b192023-01-10 04:37:28630 if (ctx.config.mingw && ret == filename)
Arthur Eubanks5f8f3102023-06-06 18:11:52631 return findLibMinGW(filename);
Rui Ueyama136d27a2019-07-11 05:40:30632 return ret;
Rui Ueyamad21b00b2015-05-31 19:17:14633}
634
635// Resolves a library path. /nodefaultlib options are taken into
636// consideration. This never returns the same path (in that case,
Kazu Hiratad6684f22022-12-11 01:04:56637// it returns std::nullopt).
Arthur Eubanks5f8f3102023-06-06 18:11:52638std::optional<StringRef> LinkerDriver::findLibIfNew(StringRef filename) {
Amy Huang5a58b192023-01-10 04:37:28639 if (ctx.config.noDefaultLibAll)
Fangrui Song9da7aee2022-11-28 00:39:40640 return std::nullopt;
Rui Ueyama136d27a2019-07-11 05:40:30641 if (!visitedLibs.insert(filename.lower()).second)
Fangrui Song9da7aee2022-11-28 00:39:40642 return std::nullopt;
Rui Ueyama4eed6cc2018-06-12 21:47:31643
Arthur Eubanks5f8f3102023-06-06 18:11:52644 StringRef path = findLib(filename);
Amy Huang5a58b192023-01-10 04:37:28645 if (ctx.config.noDefaultLibs.count(path.lower()))
Fangrui Song9da7aee2022-11-28 00:39:40646 return std::nullopt;
Rui Ueyama4eed6cc2018-06-12 21:47:31647
Fangrui Song9da7aee2022-11-28 00:39:40648 if (std::optional<sys::fs::UniqueID> id = getUniqueID(path))
Rui Ueyama136d27a2019-07-11 05:40:30649 if (!visitedFiles.insert(*id).second)
Fangrui Song9da7aee2022-11-28 00:39:40650 return std::nullopt;
Rui Ueyama136d27a2019-07-11 05:40:30651 return path;
Rui Ueyama54b71da2015-05-31 19:17:12652}
653
Jacek Caban0a9810d2024-12-15 17:41:26654void LinkerDriver::setMachine(MachineTypes machine) {
655 assert(ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN);
656 assert(machine != IMAGE_FILE_MACHINE_UNKNOWN);
657
658 ctx.config.machine = machine;
Jacek Caban16ef2392024-12-16 10:31:05659
660 if (machine != ARM64X) {
661 ctx.symtab.machine = machine;
Jacek Caban16ef2392024-12-16 10:31:05662 } else {
Jacek Caban1c05c612025-04-11 13:53:25663 ctx.symtab.machine = ARM64EC;
664 ctx.hybridSymtab.emplace(ctx, ARM64);
Jacek Caban16ef2392024-12-16 10:31:05665 }
666
Jacek Caban0a9810d2024-12-15 17:41:26667 addWinSysRootLibSearchPaths();
668}
669
Peter Kastingc5fb05f2022-02-16 14:20:03670void LinkerDriver::detectWinSysRoot(const opt::InputArgList &Args) {
671 IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
672
673 // Check the command line first, that's the user explicitly telling us what to
674 // use. Check the environment next, in case we're being invoked from a VS
675 // command prompt. Failing that, just try to find the newest Visual Studio
676 // version we can and use its default VC toolchain.
Fangrui Song900f3f92022-12-03 20:23:39677 std::optional<StringRef> VCToolsDir, VCToolsVersion, WinSysRoot;
Peter Kastingc5fb05f2022-02-16 14:20:03678 if (auto *A = Args.getLastArg(OPT_vctoolsdir))
679 VCToolsDir = A->getValue();
680 if (auto *A = Args.getLastArg(OPT_vctoolsversion))
681 VCToolsVersion = A->getValue();
682 if (auto *A = Args.getLastArg(OPT_winsysroot))
683 WinSysRoot = A->getValue();
684 if (!findVCToolChainViaCommandLine(*VFS, VCToolsDir, VCToolsVersion,
685 WinSysRoot, vcToolChainPath, vsLayout) &&
686 (Args.hasArg(OPT_lldignoreenv) ||
687 !findVCToolChainViaEnvironment(*VFS, vcToolChainPath, vsLayout)) &&
Saleem Abdulrasoolaf5f4682023-03-07 18:10:31688 !findVCToolChainViaSetupConfig(*VFS, {}, vcToolChainPath, vsLayout) &&
Peter Kastingc5fb05f2022-02-16 14:20:03689 !findVCToolChainViaRegistry(vcToolChainPath, vsLayout))
690 return;
691
692 // If the VC environment hasn't been configured (perhaps because the user did
693 // not run vcvarsall), try to build a consistent link environment. If the
694 // environment variable is set however, assume the user knows what they're
695 // doing. If the user passes /vctoolsdir or /winsdkdir, trust that over env
696 // vars.
697 if (const auto *A = Args.getLastArg(OPT_diasdkdir, OPT_winsysroot)) {
698 diaPath = A->getValue();
699 if (A->getOption().getID() == OPT_winsysroot)
700 path::append(diaPath, "DIA SDK");
701 }
702 useWinSysRootLibPath = Args.hasArg(OPT_lldignoreenv) ||
703 !Process::GetEnv("LIB") ||
704 Args.getLastArg(OPT_vctoolsdir, OPT_winsysroot);
705 if (Args.hasArg(OPT_lldignoreenv) || !Process::GetEnv("LIB") ||
706 Args.getLastArg(OPT_winsdkdir, OPT_winsysroot)) {
Fangrui Song900f3f92022-12-03 20:23:39707 std::optional<StringRef> WinSdkDir, WinSdkVersion;
Peter Kastingc5fb05f2022-02-16 14:20:03708 if (auto *A = Args.getLastArg(OPT_winsdkdir))
709 WinSdkDir = A->getValue();
710 if (auto *A = Args.getLastArg(OPT_winsdkversion))
711 WinSdkVersion = A->getValue();
712
713 if (useUniversalCRT(vsLayout, vcToolChainPath, getArch(), *VFS)) {
714 std::string UniversalCRTSdkPath;
715 std::string UCRTVersion;
716 if (getUniversalCRTSdkDir(*VFS, WinSdkDir, WinSdkVersion, WinSysRoot,
717 UniversalCRTSdkPath, UCRTVersion)) {
718 universalCRTLibPath = UniversalCRTSdkPath;
719 path::append(universalCRTLibPath, "Lib", UCRTVersion, "ucrt");
720 }
721 }
722
723 std::string sdkPath;
724 std::string windowsSDKIncludeVersion;
725 std::string windowsSDKLibVersion;
726 if (getWindowsSDKDir(*VFS, WinSdkDir, WinSdkVersion, WinSysRoot, sdkPath,
727 sdkMajor, windowsSDKIncludeVersion,
728 windowsSDKLibVersion)) {
729 windowsSdkLibPath = sdkPath;
730 path::append(windowsSdkLibPath, "Lib");
731 if (sdkMajor >= 8)
732 path::append(windowsSdkLibPath, windowsSDKLibVersion, "um");
733 }
734 }
735}
736
Tobias Hietaaf744f02023-07-14 07:46:54737void LinkerDriver::addClangLibSearchPaths(const std::string &argv0) {
738 std::string lldBinary = sys::fs::getMainExecutable(argv0.c_str(), nullptr);
739 SmallString<128> binDir(lldBinary);
Matheus Izvekova5e280b2023-09-21 11:16:11740 sys::path::remove_filename(binDir); // remove lld-link.exe
Tobias Hietaaf744f02023-07-14 07:46:54741 StringRef rootDir = sys::path::parent_path(binDir); // remove 'bin'
742
743 SmallString<128> libDir(rootDir);
744 sys::path::append(libDir, "lib");
Tobias Hietaaf744f02023-07-14 07:46:54745
746 // Add the resource dir library path
747 SmallString<128> runtimeLibDir(rootDir);
Matheus Izvekova5e280b2023-09-21 11:16:11748 sys::path::append(runtimeLibDir, "lib", "clang",
749 std::to_string(LLVM_VERSION_MAJOR), "lib");
Tobias Hietaaf744f02023-07-14 07:46:54750 // Resource dir + osname, which is hardcoded to windows since we are in the
751 // COFF driver.
752 SmallString<128> runtimeLibDirWithOS(runtimeLibDir);
753 sys::path::append(runtimeLibDirWithOS, "windows");
Martin Storsjöf906fd52023-10-02 10:47:30754
755 searchPaths.push_back(saver().save(runtimeLibDirWithOS.str()));
756 searchPaths.push_back(saver().save(runtimeLibDir.str()));
757 searchPaths.push_back(saver().save(libDir.str()));
Tobias Hietaaf744f02023-07-14 07:46:54758}
759
Peter Kastingc5fb05f2022-02-16 14:20:03760void LinkerDriver::addWinSysRootLibSearchPaths() {
761 if (!diaPath.empty()) {
762 // The DIA SDK always uses the legacy vc arch, even in new MSVC versions.
763 path::append(diaPath, "lib", archToLegacyVCArch(getArch()));
764 searchPaths.push_back(saver().save(diaPath.str()));
765 }
766 if (useWinSysRootLibPath) {
767 searchPaths.push_back(saver().save(getSubDirectoryPath(
768 SubDirectoryType::Lib, vsLayout, vcToolChainPath, getArch())));
769 searchPaths.push_back(saver().save(
770 getSubDirectoryPath(SubDirectoryType::Lib, vsLayout, vcToolChainPath,
771 getArch(), "atlmfc")));
772 }
773 if (!universalCRTLibPath.empty()) {
774 StringRef ArchName = archToWindowsSDKArch(getArch());
775 if (!ArchName.empty()) {
776 path::append(universalCRTLibPath, ArchName);
777 searchPaths.push_back(saver().save(universalCRTLibPath.str()));
778 }
779 }
780 if (!windowsSdkLibPath.empty()) {
781 std::string path;
782 if (appendArchToWindowsSDKLibPath(sdkMajor, windowsSdkLibPath, getArch(),
783 path))
784 searchPaths.push_back(saver().save(path));
785 }
A2uria90a08fb2025-03-12 06:47:01786
787 // Libraries specified by `/nodefaultlib:` may not be found in incomplete
788 // search paths before lld infers a machine type from input files.
789 std::set<std::string> noDefaultLibs;
790 for (const std::string &path : ctx.config.noDefaultLibs)
791 noDefaultLibs.insert(findLib(path).lower());
792 ctx.config.noDefaultLibs = noDefaultLibs;
Peter Kastingc5fb05f2022-02-16 14:20:03793}
794
Rui Ueyama54b71da2015-05-31 19:17:12795// Parses LIB environment which contains a list of search paths.
Rui Ueyamaf00df0a2015-06-19 22:39:48796void LinkerDriver::addLibSearchPaths() {
Krzysztof Parzyszek3c255f62022-12-06 17:53:37797 std::optional<std::string> envOpt = Process::GetEnv("LIB");
Kazu Hirata5413bf12022-06-20 18:33:56798 if (!envOpt)
Rui Ueyamaf00df0a2015-06-19 22:39:48799 return;
Alexandre Ganea83d59e02022-01-20 19:53:18800 StringRef env = saver().save(*envOpt);
Rui Ueyama136d27a2019-07-11 05:40:30801 while (!env.empty()) {
802 StringRef path;
803 std::tie(path, env) = env.split(';');
804 searchPaths.push_back(path);
Rui Ueyama54b71da2015-05-31 19:17:12805 }
Rui Ueyama54b71da2015-05-31 19:17:12806}
807
Amy Huang5a58b192023-01-10 04:37:28808uint64_t LinkerDriver::getDefaultImageBase() {
809 if (ctx.config.is64())
810 return ctx.config.dll ? 0x180000000 : 0x140000000;
811 return ctx.config.dll ? 0x10000000 : 0x400000;
Rui Ueyama5c437cd2015-07-25 21:42:33812}
813
Nico Webere6d1f262021-02-22 19:29:55814static std::string rewritePath(StringRef s) {
815 if (fs::exists(s))
816 return relativeToRoot(s);
817 return std::string(s);
818}
819
820// Reconstructs command line arguments so that so that you can re-run
821// the same command with the same inputs. This is for --reproduce.
Rui Ueyama136d27a2019-07-11 05:40:30822static std::string createResponseFile(const opt::InputArgList &args,
Rui Ueyama136d27a2019-07-11 05:40:30823 ArrayRef<StringRef> searchPaths) {
824 SmallString<0> data;
825 raw_svector_ostream os(data);
Peter Collingbournefeee2102016-07-26 02:00:42826
Rui Ueyama136d27a2019-07-11 05:40:30827 for (auto *arg : args) {
828 switch (arg->getOption().getID()) {
Peter Collingbournefeee2102016-07-26 02:00:42829 case OPT_linkrepro:
Rui Ueyama0d53ac82019-10-04 07:27:38830 case OPT_reproduce:
Peter Collingbournefeee2102016-07-26 02:00:42831 case OPT_libpath:
Peter Kastingc5fb05f2022-02-16 14:20:03832 case OPT_winsysroot:
Peter Collingbournefeee2102016-07-26 02:00:42833 break;
Nico Weber34a44b22024-12-17 16:30:13834 case OPT_INPUT:
835 os << quote(rewritePath(arg->getValue())) << "\n";
836 break;
837 case OPT_wholearchive_file:
838 os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << "\n";
839 break;
Nico Webere6d1f262021-02-22 19:29:55840 case OPT_call_graph_ordering_file:
841 case OPT_deffile:
Nico Weber400a1de2021-08-24 14:19:21842 case OPT_manifestinput:
Nico Webere6d1f262021-02-22 19:29:55843 case OPT_natvis:
844 os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << '\n';
845 break;
846 case OPT_order: {
847 StringRef orderFile = arg->getValue();
848 orderFile.consume_front("@");
849 os << arg->getSpelling() << '@' << quote(rewritePath(orderFile)) << '\n';
850 break;
851 }
852 case OPT_pdbstream: {
853 const std::pair<StringRef, StringRef> nameFile =
854 StringRef(arg->getValue()).split("=");
855 os << arg->getSpelling() << nameFile.first << '='
856 << quote(rewritePath(nameFile.second)) << '\n';
857 break;
858 }
Alexandre Ganea2769d582019-04-23 12:30:49859 case OPT_implib:
Nico Weber400a1de2021-08-24 14:19:21860 case OPT_manifestfile:
Alexandre Ganea2769d582019-04-23 12:30:49861 case OPT_pdb:
Reid Kleckner8045a8a2020-01-15 23:09:25862 case OPT_pdbstripped:
Alexandre Ganea2769d582019-04-23 12:30:49863 case OPT_out:
Rui Ueyama136d27a2019-07-11 05:40:30864 os << arg->getSpelling() << sys::path::filename(arg->getValue()) << "\n";
Alexandre Ganea2769d582019-04-23 12:30:49865 break;
Peter Collingbournefeee2102016-07-26 02:00:42866 default:
Rui Ueyama136d27a2019-07-11 05:40:30867 os << toString(*arg) << "\n";
Peter Collingbournefeee2102016-07-26 02:00:42868 }
869 }
870
Rui Ueyama136d27a2019-07-11 05:40:30871 for (StringRef path : searchPaths) {
872 std::string relPath = relativeToRoot(path);
873 os << "/libpath:" << quote(relPath) << "\n";
Peter Collingbournefeee2102016-07-26 02:00:42874 }
875
Kazu Hirata21730eb2024-01-22 08:13:23876 return std::string(data);
Peter Collingbournefeee2102016-07-26 02:00:42877}
878
Fangrui Song1534f452024-12-04 06:19:30879static unsigned parseDebugTypes(COFFLinkerContext &ctx,
880 const opt::InputArgList &args) {
Rui Ueyama136d27a2019-07-11 05:40:30881 unsigned debugTypes = static_cast<unsigned>(DebugType::None);
Will Wilson3cb18342018-09-24 15:28:03882
Rui Ueyama136d27a2019-07-11 05:40:30883 if (auto *a = args.getLastArg(OPT_debugtype)) {
884 SmallVector<StringRef, 3> types;
885 StringRef(a->getValue())
886 .split(types, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
Will Wilson3cb18342018-09-24 15:28:03887
Rui Ueyama136d27a2019-07-11 05:40:30888 for (StringRef type : types) {
889 unsigned v = StringSwitch<unsigned>(type.lower())
Will Wilson3cb18342018-09-24 15:28:03890 .Case("cv", static_cast<unsigned>(DebugType::CV))
891 .Case("pdata", static_cast<unsigned>(DebugType::PData))
892 .Case("fixup", static_cast<unsigned>(DebugType::Fixup))
893 .Default(0);
Rui Ueyama136d27a2019-07-11 05:40:30894 if (v == 0) {
Fangrui Song1534f452024-12-04 06:19:30895 Warn(ctx) << "/debugtype: unknown option '" << type << "'";
Will Wilson3cb18342018-09-24 15:28:03896 continue;
897 }
Rui Ueyama136d27a2019-07-11 05:40:30898 debugTypes |= v;
Will Wilson3cb18342018-09-24 15:28:03899 }
Rui Ueyama136d27a2019-07-11 05:40:30900 return debugTypes;
Will Wilson3cb18342018-09-24 15:28:03901 }
902
903 // Default debug types
Rui Ueyama136d27a2019-07-11 05:40:30904 debugTypes = static_cast<unsigned>(DebugType::CV);
905 if (args.hasArg(OPT_driver))
906 debugTypes |= static_cast<unsigned>(DebugType::PData);
907 if (args.hasArg(OPT_profile))
908 debugTypes |= static_cast<unsigned>(DebugType::Fixup);
Saleem Abdulrasoola2cca7e2016-08-08 22:02:44909
Rui Ueyama136d27a2019-07-11 05:40:30910 return debugTypes;
Saleem Abdulrasoola2cca7e2016-08-08 22:02:44911}
912
Amy Huang5a58b192023-01-10 04:37:28913std::string LinkerDriver::getMapFile(const opt::InputArgList &args,
914 opt::OptSpecifier os,
915 opt::OptSpecifier osFile) {
Sylvain Audib91905a2020-03-23 21:06:48916 auto *arg = args.getLastArg(os, osFile);
Rui Ueyama136d27a2019-07-11 05:40:30917 if (!arg)
Hans Wennborg1818e652016-12-09 20:54:44918 return "";
Sylvain Audib91905a2020-03-23 21:06:48919 if (arg->getOption().getID() == osFile.getID())
Rui Ueyama136d27a2019-07-11 05:40:30920 return arg->getValue();
Hans Wennborg1818e652016-12-09 20:54:44921
Sylvain Audib91905a2020-03-23 21:06:48922 assert(arg->getOption().getID() == os.getID());
Amy Huang5a58b192023-01-10 04:37:28923 StringRef outFile = ctx.config.outputFile;
Rui Ueyama136d27a2019-07-11 05:40:30924 return (outFile.substr(0, outFile.rfind('.')) + ".map").str();
Hans Wennborg1818e652016-12-09 20:54:44925}
926
Amy Huang5a58b192023-01-10 04:37:28927std::string LinkerDriver::getImplibPath() {
928 if (!ctx.config.implib.empty())
929 return std::string(ctx.config.implib);
930 SmallString<128> out = StringRef(ctx.config.outputFile);
Rui Ueyama136d27a2019-07-11 05:40:30931 sys::path::replace_extension(out, ".lib");
Kazu Hirata21730eb2024-01-22 08:13:23932 return std::string(out);
Reid Kleckner146eb7a2017-06-02 17:53:06933}
934
Nico Weber79a84762019-10-10 02:04:56935// The import name is calculated as follows:
Saleem Abdulrasoolace2fa72017-07-19 02:01:27936//
937// | LIBRARY w/ ext | LIBRARY w/o ext | no LIBRARY
938// -----+----------------+---------------------+------------------
939// LINK | {value} | {value}.{.dll/.exe} | {output name}
940// LIB | {value} | {value}.dll | {output name}.dll
941//
Amy Huang5a58b192023-01-10 04:37:28942std::string LinkerDriver::getImportName(bool asLib) {
Rui Ueyama136d27a2019-07-11 05:40:30943 SmallString<128> out;
Saleem Abdulrasoolace2fa72017-07-19 02:01:27944
Amy Huang5a58b192023-01-10 04:37:28945 if (ctx.config.importName.empty()) {
946 out.assign(sys::path::filename(ctx.config.outputFile));
Rui Ueyama136d27a2019-07-11 05:40:30947 if (asLib)
948 sys::path::replace_extension(out, ".dll");
Saleem Abdulrasoolace2fa72017-07-19 02:01:27949 } else {
Amy Huang5a58b192023-01-10 04:37:28950 out.assign(ctx.config.importName);
Rui Ueyama136d27a2019-07-11 05:40:30951 if (!sys::path::has_extension(out))
952 sys::path::replace_extension(out,
Amy Huang5a58b192023-01-10 04:37:28953 (ctx.config.dll || asLib) ? ".dll" : ".exe");
Saleem Abdulrasoolace2fa72017-07-19 02:01:27954 }
955
Kazu Hirata21730eb2024-01-22 08:13:23956 return std::string(out);
Saleem Abdulrasoolace2fa72017-07-19 02:01:27957}
958
Amy Huang5a58b192023-01-10 04:37:28959void LinkerDriver::createImportLibrary(bool asLib) {
Alexandre Ganea356139b2023-10-06 02:33:58960 llvm::TimeTraceScope timeScope("Create import library");
Jacek Cabane902cf22025-01-29 08:57:11961 std::vector<COFFShortExport> exports, nativeExports;
962
963 auto getExports = [](SymbolTable &symtab,
964 std::vector<COFFShortExport> &exports) {
965 for (Export &e1 : symtab.exports) {
966 COFFShortExport e2;
967 e2.Name = std::string(e1.name);
968 e2.SymbolName = std::string(e1.symbolName);
969 e2.ExtName = std::string(e1.extName);
970 e2.ExportAs = std::string(e1.exportAs);
971 e2.ImportName = std::string(e1.importName);
972 e2.Ordinal = e1.ordinal;
973 e2.Noname = e1.noname;
974 e2.Data = e1.data;
975 e2.Private = e1.isPrivate;
976 e2.Constant = e1.constant;
977 exports.push_back(e2);
978 }
979 };
980
Jacek Caban1c05c612025-04-11 13:53:25981 getExports(ctx.symtab, exports);
982 if (ctx.hybridSymtab)
983 getExports(*ctx.hybridSymtab, nativeExports);
Reid Kleckner146eb7a2017-06-02 17:53:06984
Rui Ueyama136d27a2019-07-11 05:40:30985 std::string libName = getImportName(asLib);
986 std::string path = getImplibPath();
Bob Haarman4ce341f2018-01-23 00:36:42987
Amy Huang5a58b192023-01-10 04:37:28988 if (!ctx.config.incremental) {
Jacek Caban46122082024-02-13 14:17:28989 checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
Jacek Cabane902cf22025-01-29 08:57:11990 ctx.config.mingw, nativeExports));
Bob Haarman5ec44852018-01-31 23:44:00991 return;
992 }
993
Bob Haarman4ce341f2018-01-23 00:36:42994 // If the import library already exists, replace it only if the contents
995 // have changed.
Rui Ueyama136d27a2019-07-11 05:40:30996 ErrorOr<std::unique_ptr<MemoryBuffer>> oldBuf = MemoryBuffer::getFile(
Abhina Sreeskantharajanc83cd8f2021-03-25 13:47:25997 path, /*IsText=*/false, /*RequiresNullTerminator=*/false);
Rui Ueyama136d27a2019-07-11 05:40:30998 if (!oldBuf) {
Jacek Caban46122082024-02-13 14:17:28999 checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
Jacek Cabane902cf22025-01-29 08:57:111000 ctx.config.mingw, nativeExports));
Bob Haarman4ce341f2018-01-23 00:36:421001 return;
1002 }
1003
Rui Ueyama136d27a2019-07-11 05:40:301004 SmallString<128> tmpName;
1005 if (std::error_code ec =
1006 sys::fs::createUniqueFile(path + ".tmp-%%%%%%%%.lib", tmpName))
Fangrui Song8b844de2024-12-06 04:18:011007 Fatal(ctx) << "cannot create temporary file for import library " << path
1008 << ": " << ec.message();
Bob Haarman4ce341f2018-01-23 00:36:421009
Jacek Cabane902cf22025-01-29 08:57:111010 if (Error e =
1011 writeImportLibrary(libName, tmpName, exports, ctx.config.machine,
1012 ctx.config.mingw, nativeExports)) {
Nico Weberf3091832021-10-04 15:45:551013 checkError(std::move(e));
Bob Haarman4ce341f2018-01-23 00:36:421014 return;
1015 }
1016
Rui Ueyama136d27a2019-07-11 05:40:301017 std::unique_ptr<MemoryBuffer> newBuf = check(MemoryBuffer::getFile(
Abhina Sreeskantharajanc83cd8f2021-03-25 13:47:251018 tmpName, /*IsText=*/false, /*RequiresNullTerminator=*/false));
Rui Ueyama136d27a2019-07-11 05:40:301019 if ((*oldBuf)->getBuffer() != newBuf->getBuffer()) {
1020 oldBuf->reset();
Nico Weberf3091832021-10-04 15:45:551021 checkError(errorCodeToError(sys::fs::rename(tmpName, path)));
Martin Storsjocf47b042018-01-30 07:26:011022 } else {
Rui Ueyama136d27a2019-07-11 05:40:301023 sys::fs::remove(tmpName);
Bob Haarman4ce341f2018-01-23 00:36:421024 }
Reid Kleckner146eb7a2017-06-02 17:53:061025}
1026
Rui Ueyama136d27a2019-07-11 05:40:301027void LinkerDriver::enqueueTask(std::function<void()> task) {
1028 taskQueue.push_back(std::move(task));
Peter Collingbourne6ee0b4e2016-12-15 04:02:231029}
1030
1031bool LinkerDriver::run() {
Alexandre Ganea356139b2023-10-06 02:33:581032 llvm::TimeTraceScope timeScope("Read input files");
Amy Huang6f7483b2021-09-16 23:48:261033 ScopedTimer t(ctx.inputFileTimer);
Zachary Turner727f1532018-01-17 19:16:261034
Rui Ueyama136d27a2019-07-11 05:40:301035 bool didWork = !taskQueue.empty();
1036 while (!taskQueue.empty()) {
1037 taskQueue.front()();
1038 taskQueue.pop_front();
Peter Collingbourne6ee0b4e2016-12-15 04:02:231039 }
Rui Ueyama136d27a2019-07-11 05:40:301040 return didWork;
Peter Collingbourne6ee0b4e2016-12-15 04:02:231041}
1042
Rui Ueyama57175aa2018-01-27 00:34:461043// Parse an /order file. If an option is given, the linker places
1044// COMDAT sections in the same order as their names appear in the
1045// given file.
Amy Huang5a58b192023-01-10 04:37:281046void LinkerDriver::parseOrderFile(StringRef arg) {
Rui Ueyama57175aa2018-01-27 00:34:461047 // For some reason, the MSVC linker requires a filename to be
1048 // preceded by "@".
Fangrui Song8d85c962023-06-05 21:36:191049 if (!arg.starts_with("@")) {
Fangrui Song8d225f12024-12-06 03:44:261050 Err(ctx) << "malformed /order option: '@' missing";
Rui Ueyama57175aa2018-01-27 00:34:461051 return;
1052 }
1053
Rui Ueyamab6d3a932018-01-29 21:50:531054 // Get a list of all comdat sections for error checking.
Rui Ueyama136d27a2019-07-11 05:40:301055 DenseSet<StringRef> set;
Jacek Caban1bd5f342025-01-16 11:55:121056 for (Chunk *c : ctx.driver.getChunks())
Rui Ueyama136d27a2019-07-11 05:40:301057 if (auto *sec = dyn_cast<SectionChunk>(c))
1058 if (sec->sym)
1059 set.insert(sec->sym->getName());
Rui Ueyamab6d3a932018-01-29 21:50:531060
Rui Ueyama57175aa2018-01-27 00:34:461061 // Open a file.
Rui Ueyama136d27a2019-07-11 05:40:301062 StringRef path = arg.substr(1);
Abhina Sreeskantharajanc83cd8f2021-03-25 13:47:251063 std::unique_ptr<MemoryBuffer> mb =
1064 CHECK(MemoryBuffer::getFile(path, /*IsText=*/false,
1065 /*RequiresNullTerminator=*/false,
1066 /*IsVolatile=*/true),
1067 "could not open " + path);
Rui Ueyama57175aa2018-01-27 00:34:461068
1069 // Parse a file. An order file contains one symbol per line.
1070 // All symbols that were not present in a given order file are
1071 // considered to have the lowest priority 0 and are placed at
1072 // end of an output section.
Benjamin Krameradcd0262020-01-28 19:23:461073 for (StringRef arg : args::getLines(mb->getMemBufferRef())) {
1074 std::string s(arg);
Amy Huang5a58b192023-01-10 04:37:281075 if (ctx.config.machine == I386 && !isDecorated(s))
Rui Ueyama136d27a2019-07-11 05:40:301076 s = "_" + s;
Rui Ueyamab6d3a932018-01-29 21:50:531077
Rui Ueyama136d27a2019-07-11 05:40:301078 if (set.count(s) == 0) {
Amy Huang5a58b192023-01-10 04:37:281079 if (ctx.config.warnMissingOrderSymbol)
Fangrui Song1534f452024-12-04 06:19:301080 Warn(ctx) << "/order:" << arg << ": missing symbol: " << s
1081 << " [LNK4037]";
Matheus Izvekova5e280b2023-09-21 11:16:111082 } else
Amy Huang5a58b192023-01-10 04:37:281083 ctx.config.order[s] = INT_MIN + ctx.config.order.size();
Rui Ueyama57175aa2018-01-27 00:34:461084 }
Nico Webere6d1f262021-02-22 19:29:551085
1086 // Include in /reproduce: output if applicable.
Amy Huang5a58b192023-01-10 04:37:281087 ctx.driver.takeBuffer(std::move(mb));
Rui Ueyama57175aa2018-01-27 00:34:461088}
1089
Amy Huang5a58b192023-01-10 04:37:281090void LinkerDriver::parseCallGraphFile(StringRef path) {
Abhina Sreeskantharajanc83cd8f2021-03-25 13:47:251091 std::unique_ptr<MemoryBuffer> mb =
1092 CHECK(MemoryBuffer::getFile(path, /*IsText=*/false,
1093 /*RequiresNullTerminator=*/false,
1094 /*IsVolatile=*/true),
1095 "could not open " + path);
Zequan Wu763671f2020-07-21 20:46:111096
1097 // Build a map from symbol name to section.
1098 DenseMap<StringRef, Symbol *> map;
Amy Huang6f7483b2021-09-16 23:48:261099 for (ObjFile *file : ctx.objFileInstances)
Zequan Wu763671f2020-07-21 20:46:111100 for (Symbol *sym : file->getSymbols())
1101 if (sym)
1102 map[sym->getName()] = sym;
1103
1104 auto findSection = [&](StringRef name) -> SectionChunk * {
1105 Symbol *sym = map.lookup(name);
1106 if (!sym) {
Amy Huang5a58b192023-01-10 04:37:281107 if (ctx.config.warnMissingOrderSymbol)
Fangrui Song1534f452024-12-04 06:19:301108 Warn(ctx) << path << ": no such symbol: " << name;
Zequan Wu763671f2020-07-21 20:46:111109 return nullptr;
1110 }
1111
1112 if (DefinedCOFF *dr = dyn_cast_or_null<DefinedCOFF>(sym))
1113 return dyn_cast_or_null<SectionChunk>(dr->getChunk());
1114 return nullptr;
1115 };
1116
1117 for (StringRef line : args::getLines(*mb)) {
1118 SmallVector<StringRef, 3> fields;
1119 line.split(fields, ' ');
1120 uint64_t count;
1121
1122 if (fields.size() != 3 || !to_integer(fields[2], count)) {
Fangrui Song8d225f12024-12-06 03:44:261123 Err(ctx) << path << ": parse error";
Zequan Wu763671f2020-07-21 20:46:111124 return;
1125 }
1126
1127 if (SectionChunk *from = findSection(fields[0]))
1128 if (SectionChunk *to = findSection(fields[1]))
Amy Huang5a58b192023-01-10 04:37:281129 ctx.config.callGraphProfile[{from, to}] += count;
Zequan Wu763671f2020-07-21 20:46:111130 }
Nico Webere6d1f262021-02-22 19:29:551131
1132 // Include in /reproduce: output if applicable.
Amy Huang5a58b192023-01-10 04:37:281133 ctx.driver.takeBuffer(std::move(mb));
Zequan Wu763671f2020-07-21 20:46:111134}
1135
Amy Huang6f7483b2021-09-16 23:48:261136static void readCallGraphsFromObjectFiles(COFFLinkerContext &ctx) {
1137 for (ObjFile *obj : ctx.objFileInstances) {
Zequan Wu763671f2020-07-21 20:46:111138 if (obj->callgraphSec) {
1139 ArrayRef<uint8_t> contents;
1140 cantFail(
1141 obj->getCOFFObj()->getSectionContents(obj->callgraphSec, contents));
Kazu Hirata4a0ccfa2023-10-13 04:21:441142 BinaryStreamReader reader(contents, llvm::endianness::little);
Zequan Wu763671f2020-07-21 20:46:111143 while (!reader.empty()) {
1144 uint32_t fromIndex, toIndex;
1145 uint64_t count;
1146 if (Error err = reader.readInteger(fromIndex))
Fangrui Song8b844de2024-12-06 04:18:011147 Fatal(ctx) << toString(obj) << ": Expected 32-bit integer";
Zequan Wu763671f2020-07-21 20:46:111148 if (Error err = reader.readInteger(toIndex))
Fangrui Song8b844de2024-12-06 04:18:011149 Fatal(ctx) << toString(obj) << ": Expected 32-bit integer";
Zequan Wu763671f2020-07-21 20:46:111150 if (Error err = reader.readInteger(count))
Fangrui Song8b844de2024-12-06 04:18:011151 Fatal(ctx) << toString(obj) << ": Expected 64-bit integer";
Zequan Wu763671f2020-07-21 20:46:111152 auto *fromSym = dyn_cast_or_null<Defined>(obj->getSymbol(fromIndex));
1153 auto *toSym = dyn_cast_or_null<Defined>(obj->getSymbol(toIndex));
1154 if (!fromSym || !toSym)
1155 continue;
1156 auto *from = dyn_cast_or_null<SectionChunk>(fromSym->getChunk());
1157 auto *to = dyn_cast_or_null<SectionChunk>(toSym->getChunk());
1158 if (from && to)
Amy Huang5a58b192023-01-10 04:37:281159 ctx.config.callGraphProfile[{from, to}] += count;
Zequan Wu763671f2020-07-21 20:46:111160 }
1161 }
1162 }
1163}
1164
Rui Ueyama136d27a2019-07-11 05:40:301165static void markAddrsig(Symbol *s) {
1166 if (auto *d = dyn_cast_or_null<Defined>(s))
1167 if (SectionChunk *c = dyn_cast_or_null<SectionChunk>(d->getChunk()))
1168 c->keepUnique = true;
Peter Collingbourneab038022018-08-23 17:44:421169}
1170
Amy Huang6f7483b2021-09-16 23:48:261171static void findKeepUniqueSections(COFFLinkerContext &ctx) {
Alexandre Ganea356139b2023-10-06 02:33:581172 llvm::TimeTraceScope timeScope("Find keep unique sections");
1173
Peter Collingbourneab038022018-08-23 17:44:421174 // Exported symbols could be address-significant in other executables or DSOs,
1175 // so we conservatively mark them as address-significant.
Jacek Caban455b3d62025-01-21 09:41:151176 ctx.forEachSymtab([](SymbolTable &symtab) {
1177 for (Export &r : symtab.exports)
1178 markAddrsig(r.sym);
1179 });
Peter Collingbourneab038022018-08-23 17:44:421180
1181 // Visit the address-significance table in each object file and mark each
1182 // referenced symbol as address-significant.
Amy Huang6f7483b2021-09-16 23:48:261183 for (ObjFile *obj : ctx.objFileInstances) {
Rui Ueyama136d27a2019-07-11 05:40:301184 ArrayRef<Symbol *> syms = obj->getSymbols();
1185 if (obj->addrsigSec) {
1186 ArrayRef<uint8_t> contents;
Fangrui Songe1cb2c02019-05-14 04:22:511187 cantFail(
Rui Ueyama136d27a2019-07-11 05:40:301188 obj->getCOFFObj()->getSectionContents(obj->addrsigSec, contents));
1189 const uint8_t *cur = contents.begin();
1190 while (cur != contents.end()) {
1191 unsigned size;
Adrian Prantl2c071812023-11-27 18:42:571192 const char *err = nullptr;
Rui Ueyama136d27a2019-07-11 05:40:301193 uint64_t symIndex = decodeULEB128(cur, &size, contents.end(), &err);
1194 if (err)
Fangrui Song8b844de2024-12-06 04:18:011195 Fatal(ctx) << toString(obj)
1196 << ": could not decode addrsig section: " << err;
Rui Ueyama136d27a2019-07-11 05:40:301197 if (symIndex >= syms.size())
Fangrui Song8b844de2024-12-06 04:18:011198 Fatal(ctx) << toString(obj)
1199 << ": invalid symbol index in addrsig section";
Rui Ueyama136d27a2019-07-11 05:40:301200 markAddrsig(syms[symIndex]);
1201 cur += size;
Peter Collingbourneab038022018-08-23 17:44:421202 }
1203 } else {
1204 // If an object file does not have an address-significance table,
1205 // conservatively mark all of its symbols as address-significant.
Rui Ueyama136d27a2019-07-11 05:40:301206 for (Symbol *s : syms)
1207 markAddrsig(s);
Peter Collingbourneab038022018-08-23 17:44:421208 }
1209 }
1210}
1211
Fangrui Song2e2038b2019-07-16 08:26:381212// link.exe replaces each %foo% in altPath with the contents of environment
Nico Weber9d752412018-10-08 23:06:051213// variable foo, and adds the two magic env vars _PDB (expands to the basename
1214// of pdb's output path) and _EXT (expands to the extension of the output
1215// binary).
1216// lld only supports %_PDB% and %_EXT% and warns on references to all other env
1217// vars.
Amy Huang5a58b192023-01-10 04:37:281218void LinkerDriver::parsePDBAltPath() {
Rui Ueyama136d27a2019-07-11 05:40:301219 SmallString<128> buf;
1220 StringRef pdbBasename =
Amy Huang5a58b192023-01-10 04:37:281221 sys::path::filename(ctx.config.pdbPath, sys::path::Style::windows);
Rui Ueyama136d27a2019-07-11 05:40:301222 StringRef binaryExtension =
Amy Huang5a58b192023-01-10 04:37:281223 sys::path::extension(ctx.config.outputFile, sys::path::Style::windows);
Rui Ueyama136d27a2019-07-11 05:40:301224 if (!binaryExtension.empty())
1225 binaryExtension = binaryExtension.substr(1); // %_EXT% does not include '.'.
Nico Weber9d752412018-10-08 23:06:051226
1227 // Invariant:
Fangrui Song2e2038b2019-07-16 08:26:381228 // +--------- cursor ('a...' might be the empty string).
1229 // | +----- firstMark
1230 // | | +- secondMark
Nico Weber9d752412018-10-08 23:06:051231 // v v v
1232 // a...%...%...
Rui Ueyama136d27a2019-07-11 05:40:301233 size_t cursor = 0;
Amy Huang5a58b192023-01-10 04:37:281234 while (cursor < ctx.config.pdbAltPath.size()) {
Rui Ueyama136d27a2019-07-11 05:40:301235 size_t firstMark, secondMark;
Amy Huang5a58b192023-01-10 04:37:281236 if ((firstMark = ctx.config.pdbAltPath.find('%', cursor)) ==
1237 StringRef::npos ||
1238 (secondMark = ctx.config.pdbAltPath.find('%', firstMark + 1)) ==
1239 StringRef::npos) {
Nico Weber9d752412018-10-08 23:06:051240 // Didn't find another full fragment, treat rest of string as literal.
Amy Huang5a58b192023-01-10 04:37:281241 buf.append(ctx.config.pdbAltPath.substr(cursor));
Nico Weber9d752412018-10-08 23:06:051242 break;
1243 }
1244
1245 // Found a full fragment. Append text in front of first %, and interpret
1246 // text between first and second % as variable name.
Amy Huang5a58b192023-01-10 04:37:281247 buf.append(ctx.config.pdbAltPath.substr(cursor, firstMark - cursor));
1248 StringRef var =
1249 ctx.config.pdbAltPath.substr(firstMark, secondMark - firstMark + 1);
Martin Storsjö3c6f8ca2021-06-24 08:06:351250 if (var.equals_insensitive("%_pdb%"))
Rui Ueyama136d27a2019-07-11 05:40:301251 buf.append(pdbBasename);
Martin Storsjö3c6f8ca2021-06-24 08:06:351252 else if (var.equals_insensitive("%_ext%"))
Rui Ueyama136d27a2019-07-11 05:40:301253 buf.append(binaryExtension);
Nico Weber9d752412018-10-08 23:06:051254 else {
Fangrui Song1534f452024-12-04 06:19:301255 Warn(ctx) << "only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping "
1256 << var << " as literal";
Rui Ueyama136d27a2019-07-11 05:40:301257 buf.append(var);
Nico Weber9d752412018-10-08 23:06:051258 }
1259
Rui Ueyama136d27a2019-07-11 05:40:301260 cursor = secondMark + 1;
Nico Weber9d752412018-10-08 23:06:051261 }
1262
Amy Huang5a58b192023-01-10 04:37:281263 ctx.config.pdbAltPath = buf;
Nico Weber9d752412018-10-08 23:06:051264}
1265
Martin Storsjo3d3a9b32019-08-30 06:56:331266/// Convert resource files and potentially merge input resource object
1267/// trees into one resource tree.
Nico Weberaf6bc652019-06-11 15:22:281268/// Call after ObjFile::Instances is complete.
Martin Storsjo3d3a9b32019-08-30 06:56:331269void LinkerDriver::convertResources() {
Alexandre Ganea356139b2023-10-06 02:33:581270 llvm::TimeTraceScope timeScope("Convert resources");
Martin Storsjo3d3a9b32019-08-30 06:56:331271 std::vector<ObjFile *> resourceObjFiles;
1272
Amy Huang6f7483b2021-09-16 23:48:261273 for (ObjFile *f : ctx.objFileInstances) {
Martin Storsjo3d3a9b32019-08-30 06:56:331274 if (f->isResourceObjFile())
1275 resourceObjFiles.push_back(f);
Nico Weberaf6bc652019-06-11 15:22:281276 }
Martin Storsjo3d3a9b32019-08-30 06:56:331277
Amy Huang5a58b192023-01-10 04:37:281278 if (!ctx.config.mingw &&
Martin Storsjo3d3a9b32019-08-30 06:56:331279 (resourceObjFiles.size() > 1 ||
1280 (resourceObjFiles.size() == 1 && !resources.empty()))) {
Fangrui Song8d225f12024-12-06 03:44:261281 Err(ctx) << (!resources.empty()
1282 ? "internal .obj file created from .res files"
1283 : toString(resourceObjFiles[1]))
1284 << ": more than one resource obj file not allowed, already got "
1285 << resourceObjFiles.front();
Martin Storsjo3d3a9b32019-08-30 06:56:331286 return;
1287 }
1288
1289 if (resources.empty() && resourceObjFiles.size() <= 1) {
1290 // No resources to convert, and max one resource object file in
1291 // the input. Keep that preconverted resource section as is.
1292 for (ObjFile *f : resourceObjFiles)
1293 f->includeResourceChunks();
1294 return;
1295 }
Amy Huang6f7483b2021-09-16 23:48:261296 ObjFile *f =
Jacek Caban9c8214f2024-12-17 18:26:131297 ObjFile::create(ctx, convertResToCOFF(resources, resourceObjFiles));
Jacek Caban84352252025-01-01 18:42:491298 addFile(f);
Martin Storsjo3d3a9b32019-08-30 06:56:331299 f->includeResourceChunks();
Nico Weberaf6bc652019-06-11 15:22:281300}
1301
Jacek Cabana2d87432024-08-22 20:03:051302void LinkerDriver::maybeCreateECExportThunk(StringRef name, Symbol *&sym) {
1303 Defined *def;
1304 if (!sym)
1305 return;
1306 if (auto undef = dyn_cast<Undefined>(sym))
Jacek Cabanba898db2024-10-15 20:58:131307 def = undef->getDefinedWeakAlias();
Jacek Cabana2d87432024-08-22 20:03:051308 else
1309 def = dyn_cast<Defined>(sym);
1310 if (!def)
1311 return;
1312
1313 if (def->getChunk()->getArm64ECRangeType() != chpe_range_type::Arm64EC)
1314 return;
1315 StringRef expName;
1316 if (auto mangledName = getArm64ECMangledFunctionName(name))
1317 expName = saver().save("EXP+" + *mangledName);
1318 else
1319 expName = saver().save("EXP+" + name);
Jacek Caban61f80db2025-04-11 16:50:161320 sym = ctx.symtab.addGCRoot(expName);
Jacek Cabana2d87432024-08-22 20:03:051321 if (auto undef = dyn_cast<Undefined>(sym)) {
1322 if (!undef->getWeakAlias()) {
1323 auto thunk = make<ECExportThunkChunk>(def);
1324 replaceSymbol<DefinedSynthetic>(undef, undef->getName(), thunk);
1325 }
1326 }
1327}
1328
1329void LinkerDriver::createECExportThunks() {
1330 // Check if EXP+ symbols have corresponding $hp_target symbols and use them
1331 // to create export thunks when available.
Jacek Caban61f80db2025-04-11 16:50:161332 for (Symbol *s : ctx.symtab.expSymbols) {
Jacek Cabana2d87432024-08-22 20:03:051333 if (!s->isUsedInRegularObj)
1334 continue;
1335 assert(s->getName().starts_with("EXP+"));
1336 std::string targetName =
1337 (s->getName().substr(strlen("EXP+")) + "$hp_target").str();
Jacek Caban61f80db2025-04-11 16:50:161338 Symbol *sym = ctx.symtab.find(targetName);
Jacek Cabana2d87432024-08-22 20:03:051339 if (!sym)
1340 continue;
1341 Defined *targetSym;
1342 if (auto undef = dyn_cast<Undefined>(sym))
Jacek Cabanba898db2024-10-15 20:58:131343 targetSym = undef->getDefinedWeakAlias();
Jacek Cabana2d87432024-08-22 20:03:051344 else
1345 targetSym = dyn_cast<Defined>(sym);
1346 if (!targetSym)
1347 continue;
1348
1349 auto *undef = dyn_cast<Undefined>(s);
1350 if (undef && !undef->getWeakAlias()) {
1351 auto thunk = make<ECExportThunkChunk>(targetSym);
1352 replaceSymbol<DefinedSynthetic>(undef, undef->getName(), thunk);
1353 }
1354 if (!targetSym->isGCRoot) {
1355 targetSym->isGCRoot = true;
1356 ctx.config.gcroot.push_back(targetSym);
1357 }
1358 }
1359
Jacek Caban61f80db2025-04-11 16:50:161360 if (ctx.symtab.entry)
1361 maybeCreateECExportThunk(ctx.symtab.entry->getName(), ctx.symtab.entry);
1362 for (Export &e : ctx.symtab.exports) {
Jacek Cabana2d87432024-08-22 20:03:051363 if (!e.data)
1364 maybeCreateECExportThunk(e.extName.empty() ? e.name : e.extName, e.sym);
1365 }
1366}
1367
Jacek Caban99a23542024-09-11 12:46:401368void LinkerDriver::pullArm64ECIcallHelper() {
1369 if (!ctx.config.arm64ECIcallHelper)
Jacek Caban251ef3f2025-01-13 22:16:571370 ctx.config.arm64ECIcallHelper =
Jacek Caban61f80db2025-04-11 16:50:161371 ctx.symtab.addGCRoot("__icall_helper_arm64ec");
Jacek Caban99a23542024-09-11 12:46:401372}
1373
Rui Ueyama659f2752019-02-19 22:06:441374// In MinGW, if no symbols are chosen to be exported, then all symbols are
1375// automatically exported by default. This behavior can be forced by the
1376// -export-all-symbols option, so that it happens even when exports are
1377// explicitly specified. The automatic behavior can be disabled using the
1378// -exclude-all-symbols option, so that lld-link behaves like link.exe rather
1379// than MinGW in the case that nothing is explicitly exported.
Rui Ueyama136d27a2019-07-11 05:40:301380void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
Rui Ueyama136d27a2019-07-11 05:40:301381 if (!args.hasArg(OPT_export_all_symbols)) {
Amy Huang5a58b192023-01-10 04:37:281382 if (!ctx.config.dll)
Martin Storsjö9dbc4b02021-07-18 19:52:321383 return;
1384
Jacek Cabanf7294772025-02-06 21:25:531385 if (ctx.symtab.hadExplicitExports ||
1386 (ctx.hybridSymtab && ctx.hybridSymtab->hadExplicitExports))
Rui Ueyama659f2752019-02-19 22:06:441387 return;
Rui Ueyama136d27a2019-07-11 05:40:301388 if (args.hasArg(OPT_exclude_all_symbols))
Rui Ueyama659f2752019-02-19 22:06:441389 return;
1390 }
1391
Jacek Cabanf7294772025-02-06 21:25:531392 ctx.forEachSymtab([&](SymbolTable &symtab) {
1393 AutoExporter exporter(symtab, excludedSymbols);
Rui Ueyama659f2752019-02-19 22:06:441394
Jacek Cabanf7294772025-02-06 21:25:531395 for (auto *arg : args.filtered(OPT_wholearchive_file))
1396 if (std::optional<StringRef> path = findFile(arg->getValue()))
1397 exporter.addWholeArchive(*path);
Rui Ueyama659f2752019-02-19 22:06:441398
Jacek Cabanf7294772025-02-06 21:25:531399 for (auto *arg : args.filtered(OPT_exclude_symbols)) {
1400 SmallVector<StringRef, 2> vec;
1401 StringRef(arg->getValue()).split(vec, ',');
1402 for (StringRef sym : vec)
1403 exporter.addExcludedSymbol(symtab.mangle(sym));
Martin Storsjö82de4e02021-04-30 12:15:131404 }
1405
Jacek Cabanf7294772025-02-06 21:25:531406 symtab.forEachSymbol([&](Symbol *s) {
1407 auto *def = dyn_cast<Defined>(s);
1408 if (!exporter.shouldExport(def))
1409 return;
1410
1411 if (!def->isGCRoot) {
1412 def->isGCRoot = true;
1413 ctx.config.gcroot.push_back(def);
1414 }
1415
1416 Export e;
1417 e.name = def->getName();
1418 e.sym = def;
1419 if (Chunk *c = def->getChunk())
1420 if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
1421 e.data = true;
1422 s->isUsedInRegularObj = true;
1423 symtab.exports.push_back(e);
1424 });
Rui Ueyama659f2752019-02-19 22:06:441425 });
1426}
1427
Rui Ueyama0d53ac82019-10-04 07:27:381428// lld has a feature to create a tar file containing all input files as well as
1429// all command line options, so that other people can run lld again with exactly
1430// the same inputs. This feature is accessible via /linkrepro and /reproduce.
1431//
1432// /linkrepro and /reproduce are very similar, but /linkrepro takes a directory
1433// name while /reproduce takes a full path. We have /linkrepro for compatibility
1434// with Microsoft link.exe.
Fangrui Song9da7aee2022-11-28 00:39:401435std::optional<std::string> getReproduceFile(const opt::InputArgList &args) {
Rui Ueyama0d53ac82019-10-04 07:27:381436 if (auto *arg = args.getLastArg(OPT_reproduce))
1437 return std::string(arg->getValue());
1438
1439 if (auto *arg = args.getLastArg(OPT_linkrepro)) {
1440 SmallString<64> path = StringRef(arg->getValue());
1441 sys::path::append(path, "repro.tar");
Jonas Devlieghere3e242422020-01-30 05:30:211442 return std::string(path);
Rui Ueyama0d53ac82019-10-04 07:27:381443 }
1444
Nico Webera0994cb2020-11-27 18:33:551445 // This is intentionally not guarded by OPT_lldignoreenv since writing
1446 // a repro tar file doesn't affect the main output.
1447 if (auto *path = getenv("LLD_REPRODUCE"))
1448 return std::string(path);
1449
Fangrui Song9da7aee2022-11-28 00:39:401450 return std::nullopt;
Rui Ueyama0d53ac82019-10-04 07:27:381451}
1452
Alex Brachetfd9962e2022-07-11 21:31:011453static std::unique_ptr<llvm::vfs::FileSystem>
Fangrui Song8d225f12024-12-06 03:44:261454getVFS(COFFLinkerContext &ctx, const opt::InputArgList &args) {
Alex Brachetfd9962e2022-07-11 21:31:011455 using namespace llvm::vfs;
1456
1457 const opt::Arg *arg = args.getLastArg(OPT_vfsoverlay);
1458 if (!arg)
1459 return nullptr;
1460
1461 auto bufOrErr = llvm::MemoryBuffer::getFile(arg->getValue());
1462 if (!bufOrErr) {
1463 checkError(errorCodeToError(bufOrErr.getError()));
1464 return nullptr;
1465 }
1466
Matheus Izvekova5e280b2023-09-21 11:16:111467 if (auto ret = vfs::getVFSFromYAML(std::move(*bufOrErr),
1468 /*DiagHandler*/ nullptr, arg->getValue()))
Alex Brachetfd9962e2022-07-11 21:31:011469 return ret;
1470
Fangrui Song8d225f12024-12-06 03:44:261471 Err(ctx) << "Invalid vfs overlay";
Alex Brachetfd9962e2022-07-11 21:31:011472 return nullptr;
1473}
1474
Miguel A. Arroyo5cd6e212024-11-12 20:30:481475constexpr const char *lldsaveTempsValues[] = {
1476 "resolution", "preopt", "promote", "internalize", "import",
1477 "opt", "precodegen", "prelink", "combinedindex"};
1478
Reshabh Sharmafdd6ed82020-12-18 06:39:011479void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
Amy Huang6f7483b2021-09-16 23:48:261480 ScopedTimer rootTimer(ctx.rootTimer);
Amy Huang5a58b192023-01-10 04:37:281481 Configuration *config = &ctx.config;
Reid Kleckner3508c1d2020-05-20 14:50:191482
Bob Haarmanf3fb7fa2019-05-08 22:11:021483 // Needed for LTO.
1484 InitializeAllTargetInfos();
1485 InitializeAllTargets();
1486 InitializeAllTargetMCs();
1487 InitializeAllAsmParsers();
1488 InitializeAllAsmPrinters();
1489
Rui Ueyama27e470a2015-08-09 20:45:171490 // If the first command line argument is "/lib", link.exe acts like lib.exe.
1491 // We call our own implementation of lib.exe that understands bitcode files.
Martin Storsjö3c6f8ca2021-06-24 08:06:351492 if (argsArr.size() > 1 &&
1493 (StringRef(argsArr[1]).equals_insensitive("/lib") ||
1494 StringRef(argsArr[1]).equals_insensitive("-lib"))) {
Rui Ueyama136d27a2019-07-11 05:40:301495 if (llvm::libDriverMain(argsArr.slice(1)) != 0)
Fangrui Song8b844de2024-12-06 04:18:011496 Fatal(ctx) << "lib failed";
Rui Ueyama27e470a2015-08-09 20:45:171497 return;
1498 }
1499
Rui Ueyama411c63602015-05-28 19:09:301500 // Parse command line options.
Amy Huang5a58b192023-01-10 04:37:281501 ArgParser parser(ctx);
Nico Weberd48ea5d2019-09-13 13:13:521502 opt::InputArgList args = parser.parse(argsArr);
Rui Ueyama411c63602015-05-28 19:09:301503
Alexandre Ganea356139b2023-10-06 02:33:581504 // Initialize time trace profiler.
1505 config->timeTraceEnabled = args.hasArg(OPT_time_trace_eq);
1506 config->timeTraceGranularity =
1507 args::getInteger(args, OPT_time_trace_granularity_eq, 500);
1508
1509 if (config->timeTraceEnabled)
1510 timeTraceProfilerInitialize(config->timeTraceGranularity, argsArr[0]);
1511
1512 llvm::TimeTraceScope timeScope("COFF link");
1513
Rui Ueyama9a3e7332017-03-30 20:10:401514 // Parse and evaluate -mllvm options.
Rui Ueyama136d27a2019-07-11 05:40:301515 std::vector<const char *> v;
1516 v.push_back("lld-link (LLVM option parsing)");
Nico Weber67d311a2022-11-14 19:23:561517 for (const auto *arg : args.filtered(OPT_mllvm)) {
Rui Ueyama136d27a2019-07-11 05:40:301518 v.push_back(arg->getValue());
Nico Weber67d311a2022-11-14 19:23:561519 config->mllvmOpts.emplace_back(arg->getValue());
1520 }
Alexandre Ganea356139b2023-10-06 02:33:581521 {
1522 llvm::TimeTraceScope timeScope2("Parse cl::opt");
1523 cl::ResetAllOptionOccurrences();
1524 cl::ParseCommandLineOptions(v.size(), v.data());
1525 }
Rui Ueyama9a3e7332017-03-30 20:10:401526
Bob Haarmanac8f7fc2017-04-05 00:43:541527 // Handle /errorlimit early, because error() depends on it.
Rui Ueyama136d27a2019-07-11 05:40:301528 if (auto *arg = args.getLastArg(OPT_errorlimit)) {
1529 int n = 20;
1530 StringRef s = arg->getValue();
1531 if (s.getAsInteger(10, n))
Fangrui Song8d225f12024-12-06 03:44:261532 Err(ctx) << arg->getSpelling() << " number expected, but got " << s;
Fangrui Song1bfe55af2024-11-17 02:31:571533 ctx.e.errorLimit = n;
Bob Haarmanac8f7fc2017-04-05 00:43:541534 }
1535
Fangrui Song8d225f12024-12-06 03:44:261536 config->vfs = getVFS(ctx, args);
Alex Brachetfd9962e2022-07-11 21:31:011537
Rui Ueyama5c726432015-05-29 16:11:521538 // Handle /help
Rui Ueyama136d27a2019-07-11 05:40:301539 if (args.hasArg(OPT_help)) {
1540 printHelp(argsArr[0]);
Rafael Espindolab835ae82015-08-06 14:58:501541 return;
Rui Ueyama5c726432015-05-29 16:11:521542 }
1543
Fangrui Songeb4663d2020-03-17 19:40:191544 // /threads: takes a positive integer and provides the default value for
1545 // /opt:lldltojobs=.
1546 if (auto *arg = args.getLastArg(OPT_threads)) {
1547 StringRef v(arg->getValue());
1548 unsigned threads = 0;
1549 if (!llvm::to_integer(v, threads, 0) || threads == 0)
Fangrui Song8d225f12024-12-06 03:44:261550 Err(ctx) << arg->getSpelling()
1551 << ": expected a positive integer, but got '" << arg->getValue()
1552 << "'";
Fangrui Songeb4663d2020-03-17 19:40:191553 parallel::strategy = hardware_concurrency(threads);
1554 config->thinLTOJobs = v.str();
1555 }
Alexandre Ganea97b2b062019-02-27 20:53:501556
Rui Ueyama136d27a2019-07-11 05:40:301557 if (args.hasArg(OPT_show_timing))
1558 config->showTiming = true;
Zachary Turner727f1532018-01-17 19:16:261559
Rui Ueyama136d27a2019-07-11 05:40:301560 config->showSummary = args.hasArg(OPT_summary);
Tobias Hieta33f93422023-07-12 07:22:061561 config->printSearchPaths = args.hasArg(OPT_print_search_paths);
Alexandre Ganea3e60ee92019-03-14 18:45:081562
Rui Ueyamaa4cf97b2017-10-23 14:57:531563 // Handle --version, which is an lld extension. This option is a bit odd
1564 // because it doesn't start with "/", but we deliberately chose "--" to
1565 // avoid conflict with /version and for compatibility with clang-cl.
Rui Ueyama136d27a2019-07-11 05:40:301566 if (args.hasArg(OPT_dash_dash_version)) {
Fangrui Songbc66e9a2024-12-04 05:29:021567 Msg(ctx) << getLLDVersion();
Rui Ueyamaa4cf97b2017-10-23 14:57:531568 return;
1569 }
1570
Martin Storsjo31fe4cd2017-09-13 19:29:391571 // Handle /lldmingw early, since it can potentially affect how other
1572 // options are handled.
Rui Ueyama136d27a2019-07-11 05:40:301573 config->mingw = args.hasArg(OPT_lldmingw);
Alvin Wongde4364f2022-11-10 11:32:071574 if (config->mingw)
1575 ctx.e.errorLimitExceededMsg = "too many errors emitted, stopping now"
1576 " (use --error-limit=0 to see all errors)";
Martin Storsjo31fe4cd2017-09-13 19:29:391577
Rui Ueyama0d53ac82019-10-04 07:27:381578 // Handle /linkrepro and /reproduce.
Alexandre Ganea356139b2023-10-06 02:33:581579 {
1580 llvm::TimeTraceScope timeScope2("Reproducer");
1581 if (std::optional<std::string> path = getReproduceFile(args)) {
1582 Expected<std::unique_ptr<TarWriter>> errOrWriter =
1583 TarWriter::create(*path, sys::path::stem(*path));
Rui Ueyama67858242019-10-04 07:27:311584
Alexandre Ganea356139b2023-10-06 02:33:581585 if (errOrWriter) {
1586 tar = std::move(*errOrWriter);
1587 } else {
Fangrui Song8d225f12024-12-06 03:44:261588 Err(ctx) << "/linkrepro: failed to open " << *path << ": "
1589 << toString(errOrWriter.takeError());
Alexandre Ganea356139b2023-10-06 02:33:581590 }
Rui Ueyama7f1f9122017-01-06 02:33:531591 }
Peter Collingbournefeee2102016-07-26 02:00:421592 }
1593
Reid Klecknerce0f3ee2019-11-07 21:50:311594 if (!args.hasArg(OPT_INPUT, OPT_wholearchive_file)) {
Rui Ueyama136d27a2019-07-11 05:40:301595 if (args.hasArg(OPT_deffile))
1596 config->noEntry = true;
Saleem Abdulrasoolbc7ff702017-06-15 20:39:581597 else
Fangrui Song8b844de2024-12-06 04:18:011598 Fatal(ctx) << "no input files";
Saleem Abdulrasoolbc7ff702017-06-15 20:39:581599 }
Rui Ueyama3d3e6fb2015-05-29 16:06:001600
Rui Ueyamaf00df0a2015-06-19 22:39:481601 // Construct search path list.
Alexandre Ganea356139b2023-10-06 02:33:581602 {
1603 llvm::TimeTraceScope timeScope2("Search paths");
1604 searchPaths.emplace_back("");
Martin Storsjö92126ca2024-01-15 20:52:571605 for (auto *arg : args.filtered(OPT_libpath))
1606 searchPaths.push_back(arg->getValue());
Martin Storsjö241c2902023-02-15 10:06:451607 if (!config->mingw) {
1608 // Prefer the Clang provided builtins over the ones bundled with MSVC.
1609 // In MinGW mode, the compiler driver passes the necessary libpath
1610 // options explicitly.
1611 addClangLibSearchPaths(argsArr[0]);
Martin Storsjö241c2902023-02-15 10:06:451612 // Don't automatically deduce the lib path from the environment or MSVC
1613 // installations when operating in mingw mode. (This also makes LLD ignore
1614 // winsysroot and vctoolsdir arguments.)
1615 detectWinSysRoot(args);
1616 if (!args.hasArg(OPT_lldignoreenv) && !args.hasArg(OPT_winsysroot))
1617 addLibSearchPaths();
1618 } else {
1619 if (args.hasArg(OPT_vctoolsdir, OPT_winsysroot))
Fangrui Song1534f452024-12-04 06:19:301620 Warn(ctx) << "ignoring /vctoolsdir or /winsysroot flags in MinGW mode";
Martin Storsjö241c2902023-02-15 10:06:451621 }
Alexandre Ganea356139b2023-10-06 02:33:581622 }
Rui Ueyamaf00df0a2015-06-19 22:39:481623
Bob Haarmane90ac012017-12-28 07:02:131624 // Handle /ignore
Rui Ueyama136d27a2019-07-11 05:40:301625 for (auto *arg : args.filtered(OPT_ignore)) {
1626 SmallVector<StringRef, 8> vec;
1627 StringRef(arg->getValue()).split(vec, ',');
1628 for (StringRef s : vec) {
1629 if (s == "4037")
1630 config->warnMissingOrderSymbol = false;
1631 else if (s == "4099")
1632 config->warnDebugInfoUnusable = false;
1633 else if (s == "4217")
1634 config->warnLocallyDefinedImported = false;
Reid Klecknerdeaf1212019-10-29 22:57:401635 else if (s == "longsections")
1636 config->warnLongSectionNames = false;
Alexandre Ganea27ba5592019-01-11 19:10:011637 // Other warning numbers are ignored.
1638 }
Bob Haarmane90ac012017-12-28 07:02:131639 }
1640
Rui Ueyamaad660982015-06-07 00:20:321641 // Handle /out
Rui Ueyama136d27a2019-07-11 05:40:301642 if (auto *arg = args.getLastArg(OPT_out))
1643 config->outputFile = arg->getValue();
Rui Ueyamaad660982015-06-07 00:20:321644
Rui Ueyama3d3e6fb2015-05-29 16:06:001645 // Handle /verbose
Rui Ueyama136d27a2019-07-11 05:40:301646 if (args.hasArg(OPT_verbose))
1647 config->verbose = true;
Fangrui Song1bfe55af2024-11-17 02:31:571648 ctx.e.verbose = config->verbose;
Rui Ueyama3d3e6fb2015-05-29 16:06:001649
Rui Ueyama95925fd2015-06-28 19:35:151650 // Handle /force or /force:unresolved
Rui Ueyama136d27a2019-07-11 05:40:301651 if (args.hasArg(OPT_force, OPT_force_unresolved))
1652 config->forceUnresolved = true;
Rui Ueyama11ca38f2018-09-13 22:05:101653
1654 // Handle /force or /force:multiple
Rui Ueyama136d27a2019-07-11 05:40:301655 if (args.hasArg(OPT_force, OPT_force_multiple))
1656 config->forceMultiple = true;
Rui Ueyama95925fd2015-06-28 19:35:151657
Nico Weber81862f82019-05-02 21:21:551658 // Handle /force or /force:multipleres
Rui Ueyama136d27a2019-07-11 05:40:301659 if (args.hasArg(OPT_force, OPT_force_multipleres))
1660 config->forceMultipleRes = true;
Nico Weber81862f82019-05-02 21:21:551661
Martin Storsjöe6e615c2023-12-15 18:07:221662 // Don't warn about long section names, such as .debug_info, for mingw (or
1663 // when -debug:dwarf is requested, handled below).
1664 if (config->mingw)
1665 config->warnLongSectionNames = false;
1666
1667 bool doGC = true;
1668
Rui Ueyama6600eb12015-07-04 23:37:321669 // Handle /debug
Martin Storsjöe6e615c2023-12-15 18:07:221670 bool shouldCreatePDB = false;
Martin Storsjöefe017f2023-12-15 18:09:241671 for (auto *arg : args.filtered(OPT_debug, OPT_debug_opt)) {
1672 std::string str;
Martin Storsjöe6e615c2023-12-15 18:07:221673 if (arg->getOption().getID() == OPT_debug)
Martin Storsjöefe017f2023-12-15 18:09:241674 str = "full";
Martin Storsjöe6e615c2023-12-15 18:07:221675 else
Martin Storsjöefe017f2023-12-15 18:09:241676 str = StringRef(arg->getValue()).lower();
1677 SmallVector<StringRef, 1> vec;
1678 StringRef(str).split(vec, ',');
1679 for (StringRef s : vec) {
1680 if (s == "fastlink") {
Fangrui Song1534f452024-12-04 06:19:301681 Warn(ctx) << "/debug:fastlink unsupported; using /debug:full";
Martin Storsjöefe017f2023-12-15 18:09:241682 s = "full";
1683 }
1684 if (s == "none") {
1685 config->debug = false;
1686 config->incremental = false;
1687 config->includeDwarfChunks = false;
1688 config->debugGHashes = false;
1689 config->writeSymtab = false;
1690 shouldCreatePDB = false;
1691 doGC = true;
1692 } else if (s == "full" || s == "ghash" || s == "noghash") {
1693 config->debug = true;
1694 config->incremental = true;
1695 config->includeDwarfChunks = true;
1696 if (s == "full" || s == "ghash")
1697 config->debugGHashes = true;
1698 shouldCreatePDB = true;
1699 doGC = false;
1700 } else if (s == "dwarf") {
1701 config->debug = true;
1702 config->incremental = true;
1703 config->includeDwarfChunks = true;
1704 config->writeSymtab = true;
1705 config->warnLongSectionNames = false;
1706 doGC = false;
Martin Storsjöe36535d2023-12-15 18:10:411707 } else if (s == "nodwarf") {
1708 config->includeDwarfChunks = false;
Martin Storsjöefe017f2023-12-15 18:09:241709 } else if (s == "symtab") {
1710 config->writeSymtab = true;
1711 doGC = false;
Martin Storsjöe36535d2023-12-15 18:10:411712 } else if (s == "nosymtab") {
1713 config->writeSymtab = false;
Martin Storsjöefe017f2023-12-15 18:09:241714 } else {
Fangrui Song8d225f12024-12-06 03:44:261715 Err(ctx) << "/debug: unknown option: " << s;
Martin Storsjöefe017f2023-12-15 18:09:241716 }
Martin Storsjöe6e615c2023-12-15 18:07:221717 }
Saleem Abdulrasoola2cca7e2016-08-08 22:02:441718 }
Rui Ueyama6600eb12015-07-04 23:37:321719
Nico Weber020d92c2019-03-11 23:02:181720 // Handle /demangle
Fangrui Songc37accf2022-03-26 07:57:061721 config->demangle = args.hasFlag(OPT_demangle, OPT_demangle_no, true);
Nico Weber020d92c2019-03-11 23:02:181722
Will Wilson3cb18342018-09-24 15:28:031723 // Handle /debugtype
Fangrui Song1534f452024-12-04 06:19:301724 config->debugTypes = parseDebugTypes(ctx, args);
Will Wilson3cb18342018-09-24 15:28:031725
Rui Ueyamaf95ed692019-11-13 04:53:151726 // Handle /driver[:uponly|:wdm].
1727 config->driverUponly = args.hasArg(OPT_driver_uponly) ||
1728 args.hasArg(OPT_driver_uponly_wdm) ||
1729 args.hasArg(OPT_driver_wdm_uponly);
1730 config->driverWdm = args.hasArg(OPT_driver_wdm) ||
1731 args.hasArg(OPT_driver_uponly_wdm) ||
1732 args.hasArg(OPT_driver_wdm_uponly);
1733 config->driver =
1734 config->driverUponly || config->driverWdm || args.hasArg(OPT_driver);
1735
Shoaib Meenaic4fdbca2017-12-15 23:52:461736 // Handle /pdb
Rui Ueyama136d27a2019-07-11 05:40:301737 if (shouldCreatePDB) {
1738 if (auto *arg = args.getLastArg(OPT_pdb))
1739 config->pdbPath = arg->getValue();
1740 if (auto *arg = args.getLastArg(OPT_pdbaltpath))
1741 config->pdbAltPath = arg->getValue();
Nico Weberf964ca82021-10-30 15:22:551742 if (auto *arg = args.getLastArg(OPT_pdbpagesize))
1743 parsePDBPageSize(arg->getValue());
Rui Ueyama136d27a2019-07-11 05:40:301744 if (args.hasArg(OPT_natvis))
1745 config->natvisFiles = args.getAllArgValues(OPT_natvis);
Eric Astora39b14f2020-04-07 20:16:221746 if (args.hasArg(OPT_pdbstream)) {
1747 for (const StringRef value : args.getAllArgValues(OPT_pdbstream)) {
1748 const std::pair<StringRef, StringRef> nameFile = value.split("=");
1749 const StringRef name = nameFile.first;
1750 const std::string file = nameFile.second.str();
1751 config->namedStreams[name] = file;
1752 }
1753 }
Takuto Ikutad8559282018-07-19 04:56:221754
Rui Ueyama136d27a2019-07-11 05:40:301755 if (auto *arg = args.getLastArg(OPT_pdb_source_path))
1756 config->pdbSourcePath = arg->getValue();
Zachary Turnerf2282762018-03-23 19:57:251757 }
Saleem Abdulrasool8fcff932016-08-29 21:20:461758
Reid Kleckner8045a8a2020-01-15 23:09:251759 // Handle /pdbstripped
Martin Storsjöe6b0ce72020-01-23 11:23:121760 if (args.hasArg(OPT_pdbstripped))
Fangrui Song1534f452024-12-04 06:19:301761 Warn(ctx) << "ignoring /pdbstripped flag, it is not yet supported";
Reid Kleckner8045a8a2020-01-15 23:09:251762
Rui Ueyamaa8b60452015-06-28 19:56:301763 // Handle /noentry
Rui Ueyama136d27a2019-07-11 05:40:301764 if (args.hasArg(OPT_noentry)) {
1765 if (args.hasArg(OPT_dll))
1766 config->noEntry = true;
Bob Haarmanac8f7fc2017-04-05 00:43:541767 else
Fangrui Song8d225f12024-12-06 03:44:261768 Err(ctx) << "/noentry must be specified with /dll";
Rui Ueyamaa8b60452015-06-28 19:56:301769 }
1770
Rui Ueyama97dff9e2015-06-17 00:16:331771 // Handle /dll
Rui Ueyama136d27a2019-07-11 05:40:301772 if (args.hasArg(OPT_dll)) {
1773 config->dll = true;
1774 config->manifestID = 2;
Rui Ueyama24c5fd02015-06-18 00:12:421775 }
Rui Ueyama97dff9e2015-06-17 00:16:331776
Shoaib Meenai59bf3622017-10-24 21:17:161777 // Handle /dynamicbase and /fixed. We can't use hasFlag for /dynamicbase
1778 // because we need to explicitly check whether that option or its inverse was
1779 // present in the argument list in order to handle /fixed.
Rui Ueyama136d27a2019-07-11 05:40:301780 auto *dynamicBaseArg = args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no);
1781 if (dynamicBaseArg &&
1782 dynamicBaseArg->getOption().getID() == OPT_dynamicbase_no)
1783 config->dynamicBase = false;
Shoaib Meenai59bf3622017-10-24 21:17:161784
Nico Webera7643792018-03-30 17:17:041785 // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the
1786 // default setting for any other project type.", but link.exe defaults to
1787 // /FIXED:NO for exe outputs as well. Match behavior, not docs.
Rui Ueyama136d27a2019-07-11 05:40:301788 bool fixed = args.hasFlag(OPT_fixed, OPT_fixed_no, false);
1789 if (fixed) {
1790 if (dynamicBaseArg &&
1791 dynamicBaseArg->getOption().getID() == OPT_dynamicbase) {
Fangrui Song8d225f12024-12-06 03:44:261792 Err(ctx) << "/fixed must not be specified with /dynamicbase";
Bob Haarmanac8f7fc2017-04-05 00:43:541793 } else {
Rui Ueyama136d27a2019-07-11 05:40:301794 config->relocatable = false;
1795 config->dynamicBase = false;
Bob Haarmanac8f7fc2017-04-05 00:43:541796 }
Rui Ueyama6592ff82015-06-16 23:13:001797 }
Rui Ueyama588e8322015-06-15 01:23:581798
Shoaib Meenai59bf3622017-10-24 21:17:161799 // Handle /appcontainer
Rui Ueyama136d27a2019-07-11 05:40:301800 config->appContainer =
1801 args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false);
Saleem Abdulrasool671029d2017-04-06 23:07:531802
Rui Ueyama3d3e6fb2015-05-29 16:06:001803 // Handle /machine
Alexandre Ganea356139b2023-10-06 02:33:581804 {
1805 llvm::TimeTraceScope timeScope2("Machine arg");
1806 if (auto *arg = args.getLastArg(OPT_machine)) {
Jacek Caban0a9810d2024-12-15 17:41:261807 MachineTypes machine = getMachineType(arg->getValue());
1808 if (machine == IMAGE_FILE_MACHINE_UNKNOWN)
Fangrui Song8b844de2024-12-06 04:18:011809 Fatal(ctx) << "unknown /machine argument: " << arg->getValue();
Jacek Caban0a9810d2024-12-15 17:41:261810 setMachine(machine);
Alexandre Ganea356139b2023-10-06 02:33:581811 }
Nico Weberb941fa82019-06-11 01:13:411812 }
Jacek Caban4e9d5a32025-01-22 22:32:181813
Rui Ueyamad21b00b2015-05-31 19:17:141814 // Handle /nodefaultlib:<filename>
Alexandre Ganea356139b2023-10-06 02:33:581815 {
1816 llvm::TimeTraceScope timeScope2("Nodefaultlib");
1817 for (auto *arg : args.filtered(OPT_nodefaultlib))
1818 config->noDefaultLibs.insert(findLib(arg->getValue()).lower());
1819 }
Rui Ueyamad21b00b2015-05-31 19:17:141820
1821 // Handle /nodefaultlib
Rui Ueyama136d27a2019-07-11 05:40:301822 if (args.hasArg(OPT_nodefaultlib_all))
1823 config->noDefaultLibAll = true;
Rui Ueyamad21b00b2015-05-31 19:17:141824
Rui Ueyama804a8b62015-05-29 16:18:151825 // Handle /base
Rui Ueyama136d27a2019-07-11 05:40:301826 if (auto *arg = args.getLastArg(OPT_base))
1827 parseNumbers(arg->getValue(), &config->imageBase);
Rui Ueyamab41b7e52015-05-29 16:21:111828
Rui Ueyama74de6202019-05-24 12:42:361829 // Handle /filealign
Rui Ueyama136d27a2019-07-11 05:40:301830 if (auto *arg = args.getLastArg(OPT_filealign)) {
1831 parseNumbers(arg->getValue(), &config->fileAlign);
1832 if (!isPowerOf2_64(config->fileAlign))
Fangrui Song8d225f12024-12-06 03:44:261833 Err(ctx) << "/filealign: not a power of two: " << config->fileAlign;
Rui Ueyama74de6202019-05-24 12:42:361834 }
1835
Rui Ueyamab41b7e52015-05-29 16:21:111836 // Handle /stack
Rui Ueyama136d27a2019-07-11 05:40:301837 if (auto *arg = args.getLastArg(OPT_stack))
1838 parseNumbers(arg->getValue(), &config->stackReserve, &config->stackCommit);
Rui Ueyama804a8b62015-05-29 16:18:151839
Reid Kleckneraf2f7da2018-02-06 01:58:261840 // Handle /guard:cf
Rui Ueyama136d27a2019-07-11 05:40:301841 if (auto *arg = args.getLastArg(OPT_guard))
1842 parseGuard(arg->getValue());
Reid Kleckneraf2f7da2018-02-06 01:58:261843
Rui Ueyamac377e9a2015-05-29 16:23:401844 // Handle /heap
Rui Ueyama136d27a2019-07-11 05:40:301845 if (auto *arg = args.getLastArg(OPT_heap))
1846 parseNumbers(arg->getValue(), &config->heapReserve, &config->heapCommit);
Rui Ueyamac377e9a2015-05-29 16:23:401847
Rui Ueyamab9dcdb52015-05-29 16:28:291848 // Handle /version
Rui Ueyama136d27a2019-07-11 05:40:301849 if (auto *arg = args.getLastArg(OPT_version))
1850 parseVersion(arg->getValue(), &config->majorImageVersion,
1851 &config->minorImageVersion);
Rui Ueyamab9dcdb52015-05-29 16:28:291852
Rui Ueyama15cc47e2015-05-29 16:34:311853 // Handle /subsystem
Rui Ueyama136d27a2019-07-11 05:40:301854 if (auto *arg = args.getLastArg(OPT_subsystem))
Martin Storsjö45c4c542020-10-03 22:29:451855 parseSubsystem(arg->getValue(), &config->subsystem,
1856 &config->majorSubsystemVersion,
1857 &config->minorSubsystemVersion);
1858
1859 // Handle /osversion
1860 if (auto *arg = args.getLastArg(OPT_osversion)) {
1861 parseVersion(arg->getValue(), &config->majorOSVersion,
1862 &config->minorOSVersion);
1863 } else {
1864 config->majorOSVersion = config->majorSubsystemVersion;
1865 config->minorOSVersion = config->minorSubsystemVersion;
1866 }
Rui Ueyama15cc47e2015-05-29 16:34:311867
Zachary Turnerc8dd6cc2018-05-17 15:11:011868 // Handle /timestamp
Rui Ueyama136d27a2019-07-11 05:40:301869 if (llvm::opt::Arg *arg = args.getLastArg(OPT_timestamp, OPT_repro)) {
1870 if (arg->getOption().getID() == OPT_repro) {
1871 config->timestamp = 0;
1872 config->repro = true;
Zachary Turnerc8dd6cc2018-05-17 15:11:011873 } else {
Rui Ueyama136d27a2019-07-11 05:40:301874 config->repro = false;
1875 StringRef value(arg->getValue());
1876 if (value.getAsInteger(0, config->timestamp))
Fangrui Song8b844de2024-12-06 04:18:011877 Fatal(ctx) << "invalid timestamp: " << value
1878 << ". Expected 32-bit integer";
Zachary Turnerc8dd6cc2018-05-17 15:11:011879 }
1880 } else {
Rui Ueyama136d27a2019-07-11 05:40:301881 config->repro = false;
Martin Storsjö0df8aed2024-02-10 21:57:121882 if (std::optional<std::string> epoch =
1883 Process::GetEnv("SOURCE_DATE_EPOCH")) {
1884 StringRef value(*epoch);
1885 if (value.getAsInteger(0, config->timestamp))
Fangrui Song8b844de2024-12-06 04:18:011886 Fatal(ctx) << "invalid SOURCE_DATE_EPOCH timestamp: " << value
1887 << ". Expected 32-bit integer";
Martin Storsjö0df8aed2024-02-10 21:57:121888 } else {
1889 config->timestamp = time(nullptr);
1890 }
Zachary Turnerc8dd6cc2018-05-17 15:11:011891 }
1892
Rui Ueyama2edb35a2015-06-18 19:09:301893 // Handle /alternatename
Rui Ueyama136d27a2019-07-11 05:40:301894 for (auto *arg : args.filtered(OPT_alternatename))
Jacek Caban1c05c612025-04-11 13:53:251895 ctx.symtab.parseAlternateName(arg->getValue());
Rui Ueyama2edb35a2015-06-18 19:09:301896
Rui Ueyama08d5e182015-06-18 23:20:111897 // Handle /include
Rui Ueyama136d27a2019-07-11 05:40:301898 for (auto *arg : args.filtered(OPT_incl))
Jacek Caban1c05c612025-04-11 13:53:251899 ctx.symtab.addGCRoot(arg->getValue());
Rui Ueyama08d5e182015-06-18 23:20:111900
Rui Ueyamab95188c2015-06-18 20:27:091901 // Handle /implib
Rui Ueyama136d27a2019-07-11 05:40:301902 if (auto *arg = args.getLastArg(OPT_implib))
1903 config->implib = arg->getValue();
Rui Ueyamab95188c2015-06-18 20:27:091904
Tobias Hieta837d16f2022-04-13 14:39:221905 config->noimplib = args.hasArg(OPT_noimplib);
Tobias Hietaeb4eef92022-04-12 14:06:461906
Martin Storsjöe6e615c2023-12-15 18:07:221907 if (args.hasArg(OPT_profile))
1908 doGC = true;
Reid Klecknerc2dcdd82017-11-13 18:38:251909 // Handle /opt.
Kazu Hiratafd8d0b02022-11-27 04:53:261910 std::optional<ICFLevel> icfLevel;
Zequan Wu5bdc5e72021-02-27 00:38:241911 if (args.hasArg(OPT_profile))
1912 icfLevel = ICFLevel::None;
Rui Ueyama136d27a2019-07-11 05:40:301913 unsigned tailMerge = 1;
rojamdb79e9902020-11-05 19:41:351914 bool ltoDebugPM = false;
Rui Ueyama136d27a2019-07-11 05:40:301915 for (auto *arg : args.filtered(OPT_opt)) {
1916 std::string str = StringRef(arg->getValue()).lower();
1917 SmallVector<StringRef, 1> vec;
1918 StringRef(str).split(vec, ',');
1919 for (StringRef s : vec) {
1920 if (s == "ref") {
1921 doGC = true;
1922 } else if (s == "noref") {
1923 doGC = false;
Fangrui Song8d85c962023-06-05 21:36:191924 } else if (s == "icf" || s.starts_with("icf=")) {
Zequan Wu5bdc5e72021-02-27 00:38:241925 icfLevel = ICFLevel::All;
1926 } else if (s == "safeicf") {
1927 icfLevel = ICFLevel::Safe;
Rui Ueyama136d27a2019-07-11 05:40:301928 } else if (s == "noicf") {
Zequan Wu5bdc5e72021-02-27 00:38:241929 icfLevel = ICFLevel::None;
Rui Ueyama136d27a2019-07-11 05:40:301930 } else if (s == "lldtailmerge") {
1931 tailMerge = 2;
1932 } else if (s == "nolldtailmerge") {
1933 tailMerge = 0;
rojamdb79e9902020-11-05 19:41:351934 } else if (s == "ltodebugpassmanager") {
1935 ltoDebugPM = true;
1936 } else if (s == "noltodebugpassmanager") {
1937 ltoDebugPM = false;
Fangrui Song05347912023-01-30 23:28:101938 } else if (s.consume_front("lldlto=")) {
1939 if (s.getAsInteger(10, config->ltoo) || config->ltoo > 3)
Fangrui Song8d225f12024-12-06 03:44:261940 Err(ctx) << "/opt:lldlto: invalid optimization level: " << s;
Scott Linder45ee0a92023-02-15 17:12:471941 } else if (s.consume_front("lldltocgo=")) {
1942 config->ltoCgo.emplace();
1943 if (s.getAsInteger(10, *config->ltoCgo) || *config->ltoCgo > 3)
Fangrui Song8d225f12024-12-06 03:44:261944 Err(ctx) << "/opt:lldltocgo: invalid codegen optimization level: "
1945 << s;
Fangrui Song05347912023-01-30 23:28:101946 } else if (s.consume_front("lldltojobs=")) {
1947 if (!get_threadpool_strategy(s))
Fangrui Song8d225f12024-12-06 03:44:261948 Err(ctx) << "/opt:lldltojobs: invalid job count: " << s;
Fangrui Song05347912023-01-30 23:28:101949 config->thinLTOJobs = s.str();
1950 } else if (s.consume_front("lldltopartitions=")) {
1951 if (s.getAsInteger(10, config->ltoPartitions) ||
Rui Ueyama136d27a2019-07-11 05:40:301952 config->ltoPartitions == 0)
Fangrui Song8d225f12024-12-06 03:44:261953 Err(ctx) << "/opt:lldltopartitions: invalid partition count: " << s;
Rui Ueyama136d27a2019-07-11 05:40:301954 } else if (s != "lbr" && s != "nolbr")
Fangrui Song8d225f12024-12-06 03:44:261955 Err(ctx) << "/opt: unknown option: " << s;
Rui Ueyamae2cbfea2015-06-07 03:17:421956 }
Rui Ueyamae2cbfea2015-06-07 03:17:421957 }
1958
Zequan Wu5bdc5e72021-02-27 00:38:241959 if (!icfLevel)
1960 icfLevel = doGC ? ICFLevel::All : ICFLevel::None;
Rui Ueyama136d27a2019-07-11 05:40:301961 config->doGC = doGC;
Kazu Hirataed8fcea2022-06-21 06:35:531962 config->doICF = *icfLevel;
Zequan Wu5bdc5e72021-02-27 00:38:241963 config->tailMerge =
1964 (tailMerge == 1 && config->doICF != ICFLevel::None) || tailMerge == 2;
rojamdb79e9902020-11-05 19:41:351965 config->ltoDebugPassManager = ltoDebugPM;
Reid Klecknerc2dcdd82017-11-13 18:38:251966
Bob Haarman69b196d2017-02-08 18:36:411967 // Handle /lldsavetemps
Miguel A. Arroyo5cd6e212024-11-12 20:30:481968 if (args.hasArg(OPT_lldsavetemps)) {
Kazu Hirata1ff74912025-03-29 17:29:451969 config->saveTempsArgs.insert_range(lldsaveTempsValues);
Miguel A. Arroyo5cd6e212024-11-12 20:30:481970 } else {
1971 for (auto *arg : args.filtered(OPT_lldsavetemps_colon)) {
1972 StringRef s = arg->getValue();
1973 if (llvm::is_contained(lldsaveTempsValues, s))
1974 config->saveTempsArgs.insert(s);
1975 else
Fangrui Song8d225f12024-12-06 03:44:261976 Err(ctx) << "unknown /lldsavetemps value: " << s;
Miguel A. Arroyo5cd6e212024-11-12 20:30:481977 }
1978 }
Bob Haarman69b196d2017-02-08 18:36:411979
Matheus Izvekov3923e612023-10-02 20:54:431980 // Handle /lldemit
1981 if (auto *arg = args.getLastArg(OPT_lldemit)) {
1982 StringRef s = arg->getValue();
1983 if (s == "obj")
1984 config->emit = EmitKind::Obj;
1985 else if (s == "llvm")
1986 config->emit = EmitKind::LLVM;
Matheus Izvekovd12b99a2023-10-03 23:24:541987 else if (s == "asm")
1988 config->emit = EmitKind::ASM;
Matheus Izvekov3923e612023-10-02 20:54:431989 else
Fangrui Song8d225f12024-12-06 03:44:261990 Err(ctx) << "/lldemit: unknown option: " << s;
Matheus Izvekov3923e612023-10-02 20:54:431991 }
1992
Martin Storsjo53518912018-03-14 20:17:161993 // Handle /kill-at
Rui Ueyama136d27a2019-07-11 05:40:301994 if (args.hasArg(OPT_kill_at))
1995 config->killAt = true;
Martin Storsjo53518912018-03-14 20:17:161996
Peter Collingbourne052e855e2017-09-08 00:50:501997 // Handle /lldltocache
Rui Ueyama136d27a2019-07-11 05:40:301998 if (auto *arg = args.getLastArg(OPT_lldltocache))
1999 config->ltoCache = arg->getValue();
Peter Collingbourne052e855e2017-09-08 00:50:502000
2001 // Handle /lldsavecachepolicy
Rui Ueyama136d27a2019-07-11 05:40:302002 if (auto *arg = args.getLastArg(OPT_lldltocachepolicy))
2003 config->ltoCachePolicy = CHECK(
2004 parseCachePruningPolicy(arg->getValue()),
2005 Twine("/lldltocachepolicy: invalid cache policy: ") + arg->getValue());
Peter Collingbourne052e855e2017-09-08 00:50:502006
Rui Ueyama8854d8a2015-06-04 19:21:242007 // Handle /failifmismatch
Rui Ueyama136d27a2019-07-11 05:40:302008 for (auto *arg : args.filtered(OPT_failifmismatch))
2009 checkFailIfMismatch(arg->getValue(), nullptr);
Rui Ueyama8854d8a2015-06-04 19:21:242010
Rui Ueyama6600eb12015-07-04 23:37:322011 // Handle /merge
Rui Ueyama136d27a2019-07-11 05:40:302012 for (auto *arg : args.filtered(OPT_merge))
2013 parseMerge(arg->getValue());
Rui Ueyama6600eb12015-07-04 23:37:322014
Peter Collingbourne66f1c9a2018-04-17 23:28:522015 // Add default section merging rules after user rules. User rules take
2016 // precedence, but we will emit a warning if there is a conflict.
2017 parseMerge(".idata=.rdata");
2018 parseMerge(".didat=.rdata");
2019 parseMerge(".edata=.rdata");
Peter Collingbourne3d636ed2018-04-20 21:32:372020 parseMerge(".xdata=.rdata");
Jacek Cabanf78024c2023-12-13 10:43:382021 parseMerge(".00cfg=.rdata");
Peter Collingbourne326f4192018-04-20 21:30:362022 parseMerge(".bss=.data");
Peter Collingbourne66f1c9a2018-04-17 23:28:522023
Jacek Caban76243ad2023-12-25 19:31:082024 if (isArm64EC(config->machine))
2025 parseMerge(".wowthk=.text");
2026
Rui Ueyama136d27a2019-07-11 05:40:302027 if (config->mingw) {
Martin Storsjocfbbb702018-08-29 17:24:102028 parseMerge(".ctors=.rdata");
2029 parseMerge(".dtors=.rdata");
2030 parseMerge(".CRT=.rdata");
jeremyd2019f66f2fe2025-05-02 07:58:142031 parseMerge(".data_cygwin_nocopy=.data");
Martin Storsjocfbbb702018-08-29 17:24:102032 }
2033
Rui Ueyama440138c2016-06-20 03:39:392034 // Handle /section
Rui Ueyama136d27a2019-07-11 05:40:302035 for (auto *arg : args.filtered(OPT_section))
2036 parseSection(arg->getValue());
Rui Ueyama440138c2016-06-20 03:39:392037
Rui Ueyamae6a33e12019-08-07 10:16:212038 // Handle /align
2039 if (auto *arg = args.getLastArg(OPT_align)) {
2040 parseNumbers(arg->getValue(), &config->align);
2041 if (!isPowerOf2_64(config->align))
Fangrui Song8d225f12024-12-06 03:44:262042 Err(ctx) << "/align: not a power of two: " << StringRef(arg->getValue());
Rui Ueyama000ff302019-11-13 04:43:252043 if (!args.hasArg(OPT_driver))
Fangrui Song1534f452024-12-04 06:19:302044 Warn(ctx) << "/align specified without /driver; image may not run";
Rui Ueyamae6a33e12019-08-07 10:16:212045 }
2046
Martin Storsjod2752aa2017-08-14 19:07:272047 // Handle /aligncomm
Rui Ueyama136d27a2019-07-11 05:40:302048 for (auto *arg : args.filtered(OPT_aligncomm))
Jacek Caban1c05c612025-04-11 13:53:252049 ctx.symtab.parseAligncomm(arg->getValue());
Martin Storsjod2752aa2017-08-14 19:07:272050
Nico Weber400a1de2021-08-24 14:19:212051 // Handle /manifestdependency.
2052 for (auto *arg : args.filtered(OPT_manifestdependency))
2053 config->manifestDependencies.insert(arg->getValue());
Nico Webera7a2c442017-07-25 18:08:032054
2055 // Handle /manifest and /manifest:
Rui Ueyama136d27a2019-07-11 05:40:302056 if (auto *arg = args.getLastArg(OPT_manifest, OPT_manifest_colon)) {
2057 if (arg->getOption().getID() == OPT_manifest)
2058 config->manifest = Configuration::SideBySide;
Nico Webera7a2c442017-07-25 18:08:032059 else
Rui Ueyama136d27a2019-07-11 05:40:302060 parseManifest(arg->getValue());
Nico Webera7a2c442017-07-25 18:08:032061 }
Rui Ueyama24c5fd02015-06-18 00:12:422062
2063 // Handle /manifestuac
Rui Ueyama136d27a2019-07-11 05:40:302064 if (auto *arg = args.getLastArg(OPT_manifestuac))
2065 parseManifestUAC(arg->getValue());
Rui Ueyama24c5fd02015-06-18 00:12:422066
Rui Ueyama24c5fd02015-06-18 00:12:422067 // Handle /manifestfile
Rui Ueyama136d27a2019-07-11 05:40:302068 if (auto *arg = args.getLastArg(OPT_manifestfile))
2069 config->manifestFile = arg->getValue();
Rui Ueyama24c5fd02015-06-18 00:12:422070
Rui Ueyamaafb19012016-04-19 01:21:582071 // Handle /manifestinput
Rui Ueyama136d27a2019-07-11 05:40:302072 for (auto *arg : args.filtered(OPT_manifestinput))
2073 config->manifestInput.push_back(arg->getValue());
Rui Ueyamaafb19012016-04-19 01:21:582074
Rui Ueyama136d27a2019-07-11 05:40:302075 if (!config->manifestInput.empty() &&
2076 config->manifest != Configuration::Embed) {
Fangrui Song8b844de2024-12-06 04:18:012077 Fatal(ctx) << "/manifestinput: requires /manifest:embed";
Nico Webera7a2c442017-07-25 18:08:032078 }
2079
Haohai Wen2a631a82023-07-01 00:58:562080 // Handle /dwodir
2081 config->dwoDir = args.getLastArgValue(OPT_dwodir);
2082
Bob Haarman63efb282019-07-11 18:03:142083 config->thinLTOEmitImportsFiles = args.hasArg(OPT_thinlto_emit_imports_files);
2084 config->thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) ||
2085 args.hasArg(OPT_thinlto_index_only_arg);
2086 config->thinLTOIndexOnlyArg =
2087 args.getLastArgValue(OPT_thinlto_index_only_arg);
Ivan Tadeu Ferreira Antunes Filho73fd9d32023-04-04 16:57:532088 std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew,
2089 config->thinLTOPrefixReplaceNativeObject) =
Fangrui Song8d225f12024-12-06 03:44:262090 getOldNewOptionsExtra(ctx, args, OPT_thinlto_prefix_replace);
Bob Haarman5011b832019-07-11 18:48:582091 config->thinLTOObjectSuffixReplace =
Fangrui Song8d225f12024-12-06 03:44:262092 getOldNewOptions(ctx, args, OPT_thinlto_object_suffix_replace);
Bob Haarman5375b942019-08-21 18:24:592093 config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path);
Yolanda Chen4f9c61e2021-03-25 02:55:182094 config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
2095 config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
chrulski-intela9fe23c2024-03-20 15:02:432096 config->ltoSampleProfileName = args.getLastArgValue(OPT_lto_sample_profile);
Rui Ueyama6592ff82015-06-16 23:13:002097 // Handle miscellaneous boolean flags.
Yolanda Chen8fa16cc2021-08-11 16:45:552098 config->ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch,
2099 OPT_lto_pgo_warn_mismatch_no, true);
Rui Ueyama136d27a2019-07-11 05:40:302100 config->allowBind = args.hasFlag(OPT_allowbind, OPT_allowbind_no, true);
2101 config->allowIsolation =
2102 args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);
2103 config->incremental =
2104 args.hasFlag(OPT_incremental, OPT_incremental_no,
Zequan Wu5bdc5e72021-02-27 00:38:242105 !config->doGC && config->doICF == ICFLevel::None &&
2106 !args.hasArg(OPT_order) && !args.hasArg(OPT_profile));
Rui Ueyama136d27a2019-07-11 05:40:302107 config->integrityCheck =
2108 args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);
Rui Ueyamaa2923b22020-03-13 10:41:182109 config->cetCompat = args.hasFlag(OPT_cetcompat, OPT_cetcompat_no, false);
Rui Ueyama136d27a2019-07-11 05:40:302110 config->nxCompat = args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
2111 for (auto *arg : args.filtered(OPT_swaprun))
2112 parseSwaprun(arg->getValue());
2113 config->terminalServerAware =
2114 !config->dll && args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
Martin Storsjö7f0e6c32020-04-25 21:49:442115 config->autoImport =
2116 args.hasFlag(OPT_auto_import, OPT_auto_import_no, config->mingw);
2117 config->pseudoRelocs = args.hasFlag(
2118 OPT_runtime_pseudo_reloc, OPT_runtime_pseudo_reloc_no, config->mingw);
Zequan Wu763671f2020-07-21 20:46:112119 config->callGraphProfileSort = args.hasFlag(
2120 OPT_call_graph_profile_sort, OPT_call_graph_profile_sort_no, true);
Martin Storsjöce211c52021-06-17 18:51:372121 config->stdcallFixup =
2122 args.hasFlag(OPT_stdcall_fixup, OPT_stdcall_fixup_no, config->mingw);
2123 config->warnStdcallFixup = !args.hasArg(OPT_stdcall_fixup);
Martin Storsjöa67ae8c2023-10-20 20:44:442124 config->allowDuplicateWeak =
2125 args.hasFlag(OPT_lld_allow_duplicate_weak,
2126 OPT_lld_allow_duplicate_weak_no, config->mingw);
Rui Ueyama6592ff82015-06-16 23:13:002127
Alvin Wong8fa0cfe2023-04-23 15:58:242128 if (args.hasFlag(OPT_inferasanlibs, OPT_inferasanlibs_no, false))
Fangrui Song1534f452024-12-04 06:19:302129 Warn(ctx) << "ignoring '/inferasanlibs', this flag is not supported";
Alvin Wong8fa0cfe2023-04-23 15:58:242130
Rui Ueyama136d27a2019-07-11 05:40:302131 if (config->incremental && args.hasArg(OPT_profile)) {
Fangrui Song1534f452024-12-04 06:19:302132 Warn(ctx) << "ignoring '/incremental' due to '/profile' specification";
Rui Ueyama136d27a2019-07-11 05:40:302133 config->incremental = false;
Nico Weber0945ad62018-03-30 17:14:502134 }
2135
Rui Ueyama136d27a2019-07-11 05:40:302136 if (config->incremental && args.hasArg(OPT_order)) {
Fangrui Song1534f452024-12-04 06:19:302137 Warn(ctx) << "ignoring '/incremental' due to '/order' specification";
Rui Ueyama136d27a2019-07-11 05:40:302138 config->incremental = false;
Nico Weber0945ad62018-03-30 17:14:502139 }
2140
Rui Ueyama136d27a2019-07-11 05:40:302141 if (config->incremental && config->doGC) {
Fangrui Song1534f452024-12-04 06:19:302142 Warn(ctx) << "ignoring '/incremental' because REF is enabled; use "
2143 "'/opt:noref' to "
2144 "disable";
Rui Ueyama136d27a2019-07-11 05:40:302145 config->incremental = false;
Bob Haarman5ec44852018-01-31 23:44:002146 }
2147
Zequan Wu5bdc5e72021-02-27 00:38:242148 if (config->incremental && config->doICF != ICFLevel::None) {
Fangrui Song1534f452024-12-04 06:19:302149 Warn(ctx) << "ignoring '/incremental' because ICF is enabled; use "
2150 "'/opt:noicf' to "
2151 "disable";
Rui Ueyama136d27a2019-07-11 05:40:302152 config->incremental = false;
Bob Haarman5ec44852018-01-31 23:44:002153 }
2154
Fangrui Song982575fd2024-12-04 04:51:502155 if (errCount(ctx))
Bob Haarmanac8f7fc2017-04-05 00:43:542156 return;
2157
Rui Ueyama136d27a2019-07-11 05:40:302158 std::set<sys::fs::UniqueID> wholeArchives;
2159 for (auto *arg : args.filtered(OPT_wholearchive_file))
Arthur Eubanks5f8f3102023-06-06 18:11:522160 if (std::optional<StringRef> path = findFile(arg->getValue()))
Fangrui Song9da7aee2022-11-28 00:39:402161 if (std::optional<sys::fs::UniqueID> id = getUniqueID(*path))
Rui Ueyama136d27a2019-07-11 05:40:302162 wholeArchives.insert(*id);
Rui Ueyama4eed6cc2018-06-12 21:47:312163
2164 // A predicate returning true if a given path is an argument for
2165 // /wholearchive:, or /wholearchive is enabled globally.
2166 // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj"
2167 // needs to be handled as "/wholearchive:foo.obj foo.obj".
Rui Ueyama136d27a2019-07-11 05:40:302168 auto isWholeArchive = [&](StringRef path) -> bool {
2169 if (args.hasArg(OPT_wholearchive_flag))
Rui Ueyama4eed6cc2018-06-12 21:47:312170 return true;
Fangrui Song9da7aee2022-11-28 00:39:402171 if (std::optional<sys::fs::UniqueID> id = getUniqueID(path))
Rui Ueyama136d27a2019-07-11 05:40:302172 return wholeArchives.count(*id);
Rui Ueyama4eed6cc2018-06-12 21:47:312173 return false;
2174 };
2175
Bob Haarman7dc5e7a02019-09-03 20:32:162176 // Create a list of input files. These can be given as OPT_INPUT options
2177 // and OPT_wholearchive_file options, and we also need to track OPT_start_lib
2178 // and OPT_end_lib.
Alexandre Ganea356139b2023-10-06 02:33:582179 {
2180 llvm::TimeTraceScope timeScope2("Parse & queue inputs");
2181 bool inLib = false;
2182 for (auto *arg : args) {
2183 switch (arg->getOption().getID()) {
2184 case OPT_end_lib:
2185 if (!inLib)
Fangrui Song8d225f12024-12-06 03:44:262186 Err(ctx) << "stray " << arg->getSpelling();
Alexandre Ganea356139b2023-10-06 02:33:582187 inLib = false;
2188 break;
2189 case OPT_start_lib:
2190 if (inLib)
Fangrui Song8d225f12024-12-06 03:44:262191 Err(ctx) << "nested " << arg->getSpelling();
Alexandre Ganea356139b2023-10-06 02:33:582192 inLib = true;
2193 break;
2194 case OPT_wholearchive_file:
2195 if (std::optional<StringRef> path = findFileIfNew(arg->getValue()))
2196 enqueuePath(*path, true, inLib);
2197 break;
2198 case OPT_INPUT:
2199 if (std::optional<StringRef> path = findFileIfNew(arg->getValue()))
2200 enqueuePath(*path, isWholeArchive(*path), inLib);
2201 break;
2202 default:
2203 // Ignore other options.
2204 break;
2205 }
Bob Haarman7dc5e7a02019-09-03 20:32:162206 }
2207 }
Rui Ueyama4eed6cc2018-06-12 21:47:312208
Peter Collingbourne8b65e512016-12-11 22:15:252209 // Read all input files given via the command line.
Peter Collingbourne6ee0b4e2016-12-15 04:02:232210 run();
Nico Weberf1828e32018-09-13 18:13:212211 if (errorCount())
2212 return;
2213
Peter Collingbourne8b65e512016-12-11 22:15:252214 // We should have inferred a machine type by now from the input files, but if
2215 // not we assume x64.
Rui Ueyama136d27a2019-07-11 05:40:302216 if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) {
Fangrui Song1534f452024-12-04 06:19:302217 Warn(ctx) << "/machine is not specified. x64 is assumed";
Jacek Caban0a9810d2024-12-15 17:41:262218 setMachine(AMD64);
Rui Ueyamaea533cd2015-07-09 19:54:132219 }
Rui Ueyama136d27a2019-07-11 05:40:302220 config->wordsize = config->is64() ? 8 : 4;
Rui Ueyamaea533cd2015-07-09 19:54:132221
Tobias Hieta33f93422023-07-12 07:22:062222 if (config->printSearchPaths) {
2223 SmallString<256> buffer;
2224 raw_svector_ostream stream(buffer);
2225 stream << "Library search paths:\n";
2226
Martin Storsjö7d7d9e42023-10-02 10:43:562227 for (StringRef path : searchPaths) {
2228 if (path == "")
2229 path = "(cwd)";
Tobias Hieta33f93422023-07-12 07:22:062230 stream << " " << path << "\n";
Martin Storsjö7d7d9e42023-10-02 10:43:562231 }
Tobias Hieta33f93422023-07-12 07:22:062232
Fangrui Song982575fd2024-12-04 04:51:502233 Msg(ctx) << buffer;
Tobias Hieta33f93422023-07-12 07:22:062234 }
2235
Peter Kastingc5fb05f2022-02-16 14:20:032236 // Process files specified as /defaultlib. These must be processed after
2237 // addWinSysRootLibSearchPaths(), which is why they are in a separate loop.
2238 for (auto *arg : args.filtered(OPT_defaultlib))
Arthur Eubanks5f8f3102023-06-06 18:11:522239 if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))
Peter Kastingc5fb05f2022-02-16 14:20:032240 enqueuePath(*path, false, false);
2241 run();
2242 if (errorCount())
2243 return;
2244
Qfrost3f558532023-01-02 09:20:152245 // Handle /RELEASE
2246 if (args.hasArg(OPT_release))
2247 config->writeCheckSum = true;
Matheus Izvekova5e280b2023-09-21 11:16:112248
Reid Klecknerfe44a532019-07-16 18:17:332249 // Handle /safeseh, x86 only, on by default, except for mingw.
Martin Storsjö745eb022020-07-27 20:44:412250 if (config->machine == I386) {
2251 config->safeSEH = args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw);
2252 config->noSEH = args.hasArg(OPT_noseh);
2253 }
Reid Klecknerfe44a532019-07-16 18:17:332254
kkent030315fb974e82025-01-20 21:38:592255 // Handle /stub
2256 if (auto *arg = args.getLastArg(OPT_stub))
2257 parseDosStub(arg->getValue());
2258
Alexandre Ganead307c4c2019-02-23 01:46:182259 // Handle /functionpadmin
Rui Ueyama136d27a2019-07-11 05:40:302260 for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt))
Amy Huang5a58b192023-01-10 04:37:282261 parseFunctionPadMin(arg);
Alexandre Ganead307c4c2019-02-23 01:46:182262
Aleksei Nurmukhametov76947e02023-11-08 20:21:052263 // Handle /dependentloadflag
2264 for (auto *arg :
2265 args.filtered(OPT_dependentloadflag, OPT_dependentloadflag_opt))
2266 parseDependentLoadFlags(arg);
2267
Peter Kastingc5fb05f2022-02-16 14:20:032268 if (tar) {
Alexandre Ganea356139b2023-10-06 02:33:582269 llvm::TimeTraceScope timeScope("Reproducer: response file");
Nico Weber34a44b22024-12-17 16:30:132270 tar->append(
2271 "response.txt",
2272 createResponseFile(args, ArrayRef<StringRef>(searchPaths).slice(1)));
Peter Kastingc5fb05f2022-02-16 14:20:032273 }
Peter Collingbournefeee2102016-07-26 02:00:422274
Rui Ueyama4d545342015-07-28 03:12:002275 // Handle /largeaddressaware
Rui Ueyama136d27a2019-07-11 05:40:302276 config->largeAddressAware = args.hasFlag(
2277 OPT_largeaddressaware, OPT_largeaddressaware_no, config->is64());
Rui Ueyama4d545342015-07-28 03:12:002278
Rui Ueyamad68e2112015-07-28 03:15:572279 // Handle /highentropyva
Rui Ueyama136d27a2019-07-11 05:40:302280 config->highEntropyVA =
2281 config->is64() &&
2282 args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true);
Rui Ueyamad68e2112015-07-28 03:15:572283
Rui Ueyama136d27a2019-07-11 05:40:302284 if (!config->dynamicBase &&
Jacek Caban85d0fbe2023-10-11 16:09:002285 (config->machine == ARMNT || isAnyArm64(config->machine)))
Fangrui Song8d225f12024-12-06 03:44:262286 Err(ctx) << "/dynamicbase:no is not compatible with "
2287 << machineToStr(config->machine);
Martin Storsjo6ea167c2017-12-12 19:39:132288
Rui Ueyamabbdec4f2015-07-09 22:51:412289 // Handle /export
Alexandre Ganea356139b2023-10-06 02:33:582290 {
2291 llvm::TimeTraceScope timeScope("Parse /export");
2292 for (auto *arg : args.filtered(OPT_export)) {
2293 Export e = parseExport(arg->getValue());
2294 if (config->machine == I386) {
2295 if (!isDecorated(e.name))
2296 e.name = saver().save("_" + e.name);
2297 if (!e.extName.empty() && !isDecorated(e.extName))
2298 e.extName = saver().save("_" + e.extName);
2299 }
Jacek Caban1c05c612025-04-11 13:53:252300 ctx.symtab.exports.push_back(e);
Rui Ueyamaf10a3202015-08-31 08:43:212301 }
Rui Ueyamabbdec4f2015-07-09 22:51:412302 }
2303
2304 // Handle /def
Rui Ueyama136d27a2019-07-11 05:40:302305 if (auto *arg = args.getLastArg(OPT_deffile)) {
Rui Ueyamabbdec4f2015-07-09 22:51:412306 // parseModuleDefs mutates Config object.
Jacek Caban1c05c612025-04-11 13:53:252307 ctx.symtab.parseModuleDefs(arg->getValue());
Jacek Caban4e9d5a32025-01-22 22:32:182308 if (ctx.hybridSymtab) {
2309 // MSVC ignores the /defArm64Native argument on non-ARM64X targets.
2310 // It is also ignored if the /def option is not specified.
2311 if (auto *arg = args.getLastArg(OPT_defarm64native))
Jacek Caban1c05c612025-04-11 13:53:252312 ctx.hybridSymtab->parseModuleDefs(arg->getValue());
Jacek Caban4e9d5a32025-01-22 22:32:182313 }
Rui Ueyamabbdec4f2015-07-09 22:51:412314 }
2315
Saleem Abdulrasoolbc7ff702017-06-15 20:39:582316 // Handle generation of import library from a def file.
Reid Klecknerce0f3ee2019-11-07 21:50:312317 if (!args.hasArg(OPT_INPUT, OPT_wholearchive_file)) {
Jacek Caban455b3d62025-01-21 09:41:152318 ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });
Tobias Hietaeb4eef92022-04-12 14:06:462319 if (!config->noimplib)
2320 createImportLibrary(/*asLib=*/true);
Rui Ueyama6f4e2552017-10-23 20:03:322321 return;
Saleem Abdulrasoolbc7ff702017-06-15 20:39:582322 }
2323
Nico Weberf4f5b7e2018-08-07 19:10:282324 // Windows specific -- if no /subsystem is given, we need to infer
2325 // that from entry point name. Must happen before /entry handling,
2326 // and after the early return when just writing an import library.
Rui Ueyama136d27a2019-07-11 05:40:302327 if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
Alexandre Ganea356139b2023-10-06 02:33:582328 llvm::TimeTraceScope timeScope("Infer subsystem");
Jacek Caban1c05c612025-04-11 13:53:252329 config->subsystem = ctx.symtab.inferSubsystem();
Rui Ueyama136d27a2019-07-11 05:40:302330 if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
Fangrui Song8b844de2024-12-06 04:18:012331 Fatal(ctx) << "subsystem must be defined";
Nico Weberf4f5b7e2018-08-07 19:10:282332 }
2333
2334 // Handle /entry and /dll
Jacek Caband0049472025-01-16 11:53:482335 ctx.forEachSymtab([&](SymbolTable &symtab) {
Alexandre Ganea356139b2023-10-06 02:33:582336 llvm::TimeTraceScope timeScope("Entry point");
2337 if (auto *arg = args.getLastArg(OPT_entry)) {
Martin Storsjöcb248f82024-06-24 17:02:392338 if (!arg->getValue()[0])
Fangrui Song8b844de2024-12-06 04:18:012339 Fatal(ctx) << "missing entry point symbol name";
Jacek Caband0049472025-01-16 11:53:482340 symtab.entry = symtab.addGCRoot(symtab.mangle(arg->getValue()), true);
2341 } else if (!symtab.entry && !config->noEntry) {
Alexandre Ganea356139b2023-10-06 02:33:582342 if (args.hasArg(OPT_dll)) {
2343 StringRef s = (config->machine == I386) ? "__DllMainCRTStartup@12"
2344 : "_DllMainCRTStartup";
Jacek Caband0049472025-01-16 11:53:482345 symtab.entry = symtab.addGCRoot(s, true);
Alexandre Ganea356139b2023-10-06 02:33:582346 } else if (config->driverWdm) {
2347 // /driver:wdm implies /entry:_NtProcessStartup
Jacek Caband0049472025-01-16 11:53:482348 symtab.entry =
2349 symtab.addGCRoot(symtab.mangle("_NtProcessStartup"), true);
Alexandre Ganea356139b2023-10-06 02:33:582350 } else {
2351 // Windows specific -- If entry point name is not given, we need to
2352 // infer that from user-defined entry name.
Jacek Caband0049472025-01-16 11:53:482353 StringRef s = symtab.findDefaultEntry();
Alexandre Ganea356139b2023-10-06 02:33:582354 if (s.empty())
Fangrui Song8b844de2024-12-06 04:18:012355 Fatal(ctx) << "entry point must be defined";
Jacek Caband0049472025-01-16 11:53:482356 symtab.entry = symtab.addGCRoot(s, true);
Fangrui Song4639a9a2024-12-04 17:04:402357 Log(ctx) << "Entry name inferred: " << s;
Alexandre Ganea356139b2023-10-06 02:33:582358 }
Nico Weberf4f5b7e2018-08-07 19:10:282359 }
Jacek Caband0049472025-01-16 11:53:482360 });
Nico Weberf4f5b7e2018-08-07 19:10:282361
Rui Ueyama6d249082015-07-13 22:31:452362 // Handle /delayload
Alexandre Ganea356139b2023-10-06 02:33:582363 {
2364 llvm::TimeTraceScope timeScope("Delay load");
2365 for (auto *arg : args.filtered(OPT_delayload)) {
2366 config->delayLoads.insert(StringRef(arg->getValue()).lower());
Jacek Caban97aa56a2025-01-28 11:07:352367 ctx.forEachSymtab([&](SymbolTable &symtab) {
2368 if (symtab.machine == I386) {
2369 symtab.delayLoadHelper = symtab.addGCRoot("___delayLoadHelper2@8");
2370 } else {
2371 symtab.delayLoadHelper = symtab.addGCRoot("__delayLoadHelper2", true);
2372 }
2373 });
Rui Ueyama6d249082015-07-13 22:31:452374 }
2375 }
2376
Reid Kleckner7668182e2017-03-21 00:12:512377 // Set default image name if neither /out or /def set it.
Rui Ueyama136d27a2019-07-11 05:40:302378 if (config->outputFile.empty()) {
Reid Klecknerce0f3ee2019-11-07 21:50:312379 config->outputFile = getOutputPath(
Amy Huang5a58b192023-01-10 04:37:282380 (*args.filtered(OPT_INPUT, OPT_wholearchive_file).begin())->getValue(),
2381 config->dll, config->driver);
Reid Kleckner7668182e2017-03-21 00:12:512382 }
2383
Rui Ueyama7fd99fc2019-03-11 16:30:552384 // Fail early if an output file is not writable.
Rui Ueyama136d27a2019-07-11 05:40:302385 if (auto e = tryCreateFile(config->outputFile)) {
Fangrui Song8d225f12024-12-06 03:44:262386 Err(ctx) << "cannot open output file " << config->outputFile << ": "
2387 << e.message();
Rui Ueyama7fd99fc2019-03-11 16:30:552388 return;
2389 }
2390
Pengxuan Zheng961c45f2022-09-23 19:39:342391 config->lldmapFile = getMapFile(args, OPT_lldmap, OPT_lldmap_file);
2392 config->mapFile = getMapFile(args, OPT_map, OPT_map_file);
2393
2394 if (config->mapFile != "" && args.hasArg(OPT_map_info)) {
2395 for (auto *arg : args.filtered(OPT_map_info)) {
2396 std::string s = StringRef(arg->getValue()).lower();
2397 if (s == "exports")
2398 config->mapInfo = true;
2399 else
Fangrui Song8d225f12024-12-06 03:44:262400 Err(ctx) << "unknown option: /mapinfo:" << s;
Pengxuan Zheng961c45f2022-09-23 19:39:342401 }
2402 }
2403
2404 if (config->lldmapFile != "" && config->lldmapFile == config->mapFile) {
Fangrui Song1534f452024-12-04 06:19:302405 Warn(ctx) << "/lldmap and /map have the same output file '"
2406 << config->mapFile << "'.\n>>> ignoring /lldmap";
Pengxuan Zheng961c45f2022-09-23 19:39:342407 config->lldmapFile.clear();
2408 }
2409
Zequan Wuaaf3a8d2023-12-05 19:57:452410 // If should create PDB, use the hash of PDB content for build id. Otherwise,
2411 // generate using the hash of executable content.
2412 if (args.hasFlag(OPT_build_id, OPT_build_id_no, false))
2413 config->buildIDHash = BuildIDHash::Binary;
2414
Rui Ueyama136d27a2019-07-11 05:40:302415 if (shouldCreatePDB) {
Peter Collingbourne94aa62e2018-04-17 23:28:382416 // Put the PDB next to the image if no /pdb flag was passed.
Rui Ueyama136d27a2019-07-11 05:40:302417 if (config->pdbPath.empty()) {
2418 config->pdbPath = config->outputFile;
2419 sys::path::replace_extension(config->pdbPath, ".pdb");
Peter Collingbourne94aa62e2018-04-17 23:28:382420 }
2421
2422 // The embedded PDB path should be the absolute path to the PDB if no
2423 // /pdbaltpath flag was passed.
Rui Ueyama136d27a2019-07-11 05:40:302424 if (config->pdbAltPath.empty()) {
2425 config->pdbAltPath = config->pdbPath;
Zachary Turnere2ce2a52018-07-12 03:22:392426
2427 // It's important to make the path absolute and remove dots. This path
2428 // will eventually be written into the PE header, and certain Microsoft
2429 // tools won't work correctly if these assumptions are not held.
Rui Ueyama136d27a2019-07-11 05:40:302430 sys::fs::make_absolute(config->pdbAltPath);
2431 sys::path::remove_dots(config->pdbAltPath);
Nico Weber9d752412018-10-08 23:06:052432 } else {
Amy Huang5a58b192023-01-10 04:37:282433 // Don't do this earlier, so that ctx.OutputFile is ready.
2434 parsePDBAltPath();
Peter Collingbourne94aa62e2018-04-17 23:28:382435 }
Zequan Wuaaf3a8d2023-12-05 19:57:452436 config->buildIDHash = BuildIDHash::PDB;
Reid Kleckner13bdbfb2017-03-22 00:57:142437 }
2438
Rui Ueyama5c437cd2015-07-25 21:42:332439 // Set default image base if /base is not given.
Rui Ueyama136d27a2019-07-11 05:40:302440 if (config->imageBase == uint64_t(-1))
2441 config->imageBase = getDefaultImageBase();
Rui Ueyama5c437cd2015-07-25 21:42:332442
Jacek Caban16ef2392024-12-16 10:31:052443 ctx.forEachSymtab([&](SymbolTable &symtab) {
Jacek Cabanf22af592025-01-15 14:21:062444 symtab.addSynthetic(symtab.mangle("__ImageBase"), nullptr);
Jacek Caban16ef2392024-12-16 10:31:052445 if (symtab.machine == I386) {
2446 symtab.addAbsolute("___safe_se_handler_table", 0);
2447 symtab.addAbsolute("___safe_se_handler_count", 0);
2448 }
Rui Ueyamabbdec4f2015-07-09 22:51:412449
Jacek Cabanf22af592025-01-15 14:21:062450 symtab.addAbsolute(symtab.mangle("__guard_fids_count"), 0);
2451 symtab.addAbsolute(symtab.mangle("__guard_fids_table"), 0);
2452 symtab.addAbsolute(symtab.mangle("__guard_flags"), 0);
2453 symtab.addAbsolute(symtab.mangle("__guard_iat_count"), 0);
2454 symtab.addAbsolute(symtab.mangle("__guard_iat_table"), 0);
2455 symtab.addAbsolute(symtab.mangle("__guard_longjmp_count"), 0);
2456 symtab.addAbsolute(symtab.mangle("__guard_longjmp_table"), 0);
Jacek Caban16ef2392024-12-16 10:31:052457 // Needed for MSVC 2017 15.5 CRT.
Jacek Cabanf22af592025-01-15 14:21:062458 symtab.addAbsolute(symtab.mangle("__enclave_config"), 0);
Jacek Caban16ef2392024-12-16 10:31:052459 // Needed for MSVC 2019 16.8 CRT.
Jacek Cabanf22af592025-01-15 14:21:062460 symtab.addAbsolute(symtab.mangle("__guard_eh_cont_count"), 0);
2461 symtab.addAbsolute(symtab.mangle("__guard_eh_cont_table"), 0);
Rui Ueyama107db552015-08-09 21:01:062462
Jacek Cabandb7123f2024-12-29 13:04:002463 if (symtab.isEC()) {
Jacek Caban16ef2392024-12-16 10:31:052464 symtab.addAbsolute("__arm64x_extra_rfe_table", 0);
2465 symtab.addAbsolute("__arm64x_extra_rfe_table_size", 0);
2466 symtab.addAbsolute("__arm64x_redirection_metadata", 0);
2467 symtab.addAbsolute("__arm64x_redirection_metadata_count", 0);
2468 symtab.addAbsolute("__hybrid_auxiliary_delayload_iat_copy", 0);
2469 symtab.addAbsolute("__hybrid_auxiliary_delayload_iat", 0);
2470 symtab.addAbsolute("__hybrid_auxiliary_iat", 0);
2471 symtab.addAbsolute("__hybrid_auxiliary_iat_copy", 0);
2472 symtab.addAbsolute("__hybrid_code_map", 0);
2473 symtab.addAbsolute("__hybrid_code_map_count", 0);
2474 symtab.addAbsolute("__hybrid_image_info_bitfield", 0);
2475 symtab.addAbsolute("__x64_code_ranges_to_entry_points", 0);
2476 symtab.addAbsolute("__x64_code_ranges_to_entry_points_count", 0);
2477 symtab.addSynthetic("__guard_check_icall_a64n_fptr", nullptr);
2478 symtab.addSynthetic("__arm64x_native_entrypoint", nullptr);
2479 }
Jacek Cabanfe2bd122023-11-15 11:35:452480
Jacek Caban16ef2392024-12-16 10:31:052481 if (config->pseudoRelocs) {
Jacek Cabanf22af592025-01-15 14:21:062482 symtab.addAbsolute(symtab.mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);
2483 symtab.addAbsolute(symtab.mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);
Jacek Caban16ef2392024-12-16 10:31:052484 }
2485 if (config->mingw) {
Jacek Cabanf22af592025-01-15 14:21:062486 symtab.addAbsolute(symtab.mangle("__CTOR_LIST__"), 0);
2487 symtab.addAbsolute(symtab.mangle("__DTOR_LIST__"), 0);
jeremyd2019f66f2fe2025-05-02 07:58:142488 symtab.addAbsolute("__data_start__", 0);
2489 symtab.addAbsolute("__data_end__", 0);
2490 symtab.addAbsolute("__bss_start__", 0);
2491 symtab.addAbsolute("__bss_end__", 0);
Jacek Caban16ef2392024-12-16 10:31:052492 }
2493 if (config->debug || config->buildIDHash != BuildIDHash::None)
2494 if (symtab.findUnderscore("__buildid"))
Jacek Cabanf22af592025-01-15 14:21:062495 symtab.addUndefined(symtab.mangle("__buildid"));
Jacek Caban16ef2392024-12-16 10:31:052496 });
Martin Storsjoeac1b052018-08-27 08:43:312497
Peter Collingbourne6ee0b4e2016-12-15 04:02:232498 // This code may add new undefined symbols to the link, which may enqueue more
2499 // symbol resolution tasks, so we need to continue executing tasks until we
2500 // converge.
Alexandre Ganea356139b2023-10-06 02:33:582501 {
2502 llvm::TimeTraceScope timeScope("Add unresolved symbols");
2503 do {
Jacek Caband0049472025-01-16 11:53:482504 ctx.forEachSymtab([&](SymbolTable &symtab) {
2505 // Windows specific -- if entry point is not found,
2506 // search for its mangled names.
2507 if (symtab.entry)
2508 symtab.mangleMaybe(symtab.entry);
Rui Ueyama85225b02015-07-02 03:15:152509
Jacek Caban455b3d62025-01-21 09:41:152510 // Windows specific -- Make sure we resolve all dllexported symbols.
2511 for (Export &e : symtab.exports) {
2512 if (!e.forwardTo.empty())
2513 continue;
2514 e.sym = symtab.addGCRoot(e.name, !e.data);
2515 if (e.source != ExportSource::Directives)
2516 e.symbolName = symtab.mangleMaybe(e.sym);
2517 }
Rui Ueyama2edb35a2015-06-18 19:09:302518
Jacek Caban8616c872025-02-21 11:52:282519 // Add weak aliases. Weak aliases is a mechanism to give remaining
2520 // undefined symbols final chance to be resolved successfully.
2521 for (auto pair : symtab.alternateNames) {
2522 StringRef from = pair.first;
2523 StringRef to = pair.second;
2524 Symbol *sym = symtab.find(from);
2525 if (!sym)
2526 continue;
2527 if (auto *u = dyn_cast<Undefined>(sym)) {
2528 if (u->weakAlias) {
2529 // On ARM64EC, anti-dependency aliases are treated as undefined
2530 // symbols unless a demangled symbol aliases a defined one, which
2531 // is part of the implementation.
2532 if (!symtab.isEC() || !u->isAntiDep)
2533 continue;
2534 if (!isa<Undefined>(u->weakAlias) &&
2535 !isArm64ECMangledFunctionName(u->getName()))
2536 continue;
2537 }
2538 u->setWeakAlias(symtab.addUndefined(to));
Jacek Caban6bb69222024-10-25 09:53:472539 }
Jacek Caban6bb69222024-10-25 09:53:472540 }
Peter Collingbourne8b65e512016-12-11 22:15:252541
Jacek Cabanb068f2f2025-01-17 10:36:122542 // If any inputs are bitcode files, the LTO code generator may create
2543 // references to library functions that are not explicit in the bitcode
2544 // file's symbol table. If any of those library functions are defined in
2545 // a bitcode file in an archive member, we need to arrange to use LTO to
2546 // compile those archive members by adding them to the link beforehand.
2547 if (!symtab.bitcodeFileInstances.empty()) {
2548 llvm::Triple TT(
2549 symtab.bitcodeFileInstances.front()->obj->getTargetTriple());
2550 for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))
2551 symtab.addLibcall(s);
2552 }
2553
Jacek Caban80084e92025-01-15 16:43:332554 // Windows specific -- if __load_config_used can be resolved, resolve
2555 // it.
2556 if (symtab.findUnderscore("_load_config_used"))
2557 symtab.addGCRoot(symtab.mangle("_load_config_used"));
Peter Collingbourne8b65e512016-12-11 22:15:252558
Jacek Caban65365792025-02-10 21:01:532559 if (args.hasArg(OPT_include_optional)) {
2560 // Handle /includeoptional
2561 for (auto *arg : args.filtered(OPT_include_optional))
2562 if (isa_and_nonnull<LazyArchive>(symtab.find(arg->getValue())))
2563 symtab.addGCRoot(arg->getValue());
2564 }
2565 });
Alexandre Ganea356139b2023-10-06 02:33:582566 } while (run());
2567 }
Martin Storsjoc02f6bf2019-06-08 18:26:182568
Miguel A. Arroyob9bd8ca2024-09-24 20:57:012569 // Handle /includeglob
2570 for (StringRef pat : args::getStrings(args, OPT_incl_glob))
Jacek Caban2d0eb5df2025-03-03 21:39:422571 ctx.forEachSymtab(
2572 [&](SymbolTable &symtab) { symtab.addUndefinedGlob(pat); });
Miguel A. Arroyob9bd8ca2024-09-24 20:57:012573
Martin Storsjö3785a412020-10-06 10:54:492574 // Create wrapped symbols for -wrap option.
Jacek Caban94d95632025-02-10 21:52:112575 ctx.forEachSymtab([&](SymbolTable &symtab) {
2576 addWrappedSymbols(symtab, args);
2577 // Load more object files that might be needed for wrapped symbols.
2578 if (!symtab.wrapped.empty())
2579 while (run())
2580 ;
2581 });
Martin Storsjö3785a412020-10-06 10:54:492582
Martin Storsjöce211c52021-06-17 18:51:372583 if (config->autoImport || config->stdcallFixup) {
Martin Storsjö7f0e6c32020-04-25 21:49:442584 // MinGW specific.
Martin Storsjoeac1b052018-08-27 08:43:312585 // Load any further object files that might be needed for doing automatic
Martin Storsjöce211c52021-06-17 18:51:372586 // imports, and do stdcall fixups.
Martin Storsjoeac1b052018-08-27 08:43:312587 //
2588 // For cases with no automatically imported symbols, this iterates once
2589 // over the symbol table and doesn't do anything.
2590 //
2591 // For the normal case with a few automatically imported symbols, this
2592 // should only need to be run once, since each new object file imported
2593 // is an import library and wouldn't add any new undefined references,
2594 // but there's nothing stopping the __imp_ symbols from coming from a
2595 // normal object file as well (although that won't be used for the
2596 // actual autoimport later on). If this pass adds new undefined references,
2597 // we won't iterate further to resolve them.
Martin Storsjöce211c52021-06-17 18:51:372598 //
2599 // If stdcall fixups only are needed for loading import entries from
2600 // a DLL without import library, this also just needs running once.
2601 // If it ends up pulling in more object files from static libraries,
2602 // (and maybe doing more stdcall fixups along the way), this would need
2603 // to loop these two calls.
Jacek Cabanc6598f62025-03-02 12:10:502604 ctx.forEachSymtab([](SymbolTable &symtab) { symtab.loadMinGWSymbols(); });
Martin Storsjoeac1b052018-08-27 08:43:312605 run();
2606 }
2607
Bob Haarman51dcb292019-07-26 17:56:452608 // At this point, we should not have any symbols that cannot be resolved.
2609 // If we are going to do codegen for link-time optimization, check for
2610 // unresolvable symbols first, so we don't spend time generating code that
2611 // will fail to link anyway.
Jacek Cabanb068f2f2025-01-17 10:36:122612 if (!config->forceUnresolved)
2613 ctx.forEachSymtab([](SymbolTable &symtab) {
2614 if (!symtab.bitcodeFileInstances.empty())
2615 symtab.reportUnresolvable();
2616 });
Bob Haarman51dcb292019-07-26 17:56:452617 if (errorCount())
2618 return;
2619
Jacek Caban455b3d62025-01-21 09:41:152620 ctx.forEachSymtab([](SymbolTable &symtab) {
2621 symtab.hadExplicitExports = !symtab.exports.empty();
2622 });
Martin Storsjö33b71ec2021-04-29 11:06:242623 if (config->mingw) {
2624 // In MinGW, all symbols are automatically exported if no symbols
2625 // are chosen to be exported.
2626 maybeExportMinGWSymbols(args);
2627 }
2628
Bob Haarman51dcb292019-07-26 17:56:452629 // Do LTO by compiling bitcode input files to a set of native COFF files then
2630 // link those files (unless -thinlto-index-only was given, in which case we
2631 // resolve symbols and write indices, but don't generate native code or link).
Jacek Caban84352252025-01-01 18:42:492632 ltoCompilationDone = true;
Jacek Cabanb068f2f2025-01-17 10:36:122633 ctx.forEachSymtab([](SymbolTable &symtab) { symtab.compileBitcodeFiles(); });
Bob Haarman51dcb292019-07-26 17:56:452634
Martin Storsjö303370e82023-11-07 09:49:052635 if (Defined *d =
2636 dyn_cast_or_null<Defined>(ctx.symtab.findUnderscore("_tls_used")))
2637 config->gcroot.push_back(d);
2638
Bob Haarman51dcb292019-07-26 17:56:452639 // If -thinlto-index-only is given, we should create only "index
2640 // files" and not object files. Index file creation is already done
Amy Huang5a58b192023-01-10 04:37:282641 // in addCombinedLTOObject, so we are done if that's the case.
Matheus Izvekov3923e612023-10-02 20:54:432642 // Likewise, don't emit object files for other /lldemit options.
2643 if (config->emit != EmitKind::Obj || config->thinLTOIndexOnly)
Bob Haarman51dcb292019-07-26 17:56:452644 return;
2645
2646 // If we generated native object files from bitcode files, this resolves
2647 // references to the symbols we use from them.
2648 run();
2649
Martin Storsjö3785a412020-10-06 10:54:492650 // Apply symbol renames for -wrap.
Jacek Caban94d95632025-02-10 21:52:112651 ctx.forEachSymtab([](SymbolTable &symtab) {
2652 if (!symtab.wrapped.empty())
2653 wrapSymbols(symtab);
2654 });
Martin Storsjö3785a412020-10-06 10:54:492655
Jacek Cabana2d87432024-08-22 20:03:052656 if (isArm64EC(config->machine))
2657 createECExportThunks();
2658
Bob Haarman51dcb292019-07-26 17:56:452659 // Resolve remaining undefined symbols and warn about imported locals.
Alexandre Ganeac75eac7c2025-04-07 15:34:242660 ctx.forEachSymtab(
2661 [&](SymbolTable &symtab) { symtab.resolveRemainingUndefines(); });
Mike Hommey6a1bdd92024-10-03 19:53:262662
Bob Haarmanb8a59c82017-10-25 22:28:382663 if (errorCount())
Rui Ueyamacc6738a2017-10-06 23:43:542664 return;
Peter Collingbourne2612a322015-07-04 05:28:412665
Rui Ueyama136d27a2019-07-11 05:40:302666 if (config->mingw) {
Martin Storsjocdf126e2019-04-15 10:57:442667 // Make sure the crtend.o object is the last object file. This object
2668 // file can contain terminating section chunks that need to be placed
2669 // last. GNU ld processes files and static libraries explicitly in the
2670 // order provided on the command line, while lld will pull in needed
2671 // files from static libraries only after the last object file on the
2672 // command line.
Amy Huang6f7483b2021-09-16 23:48:262673 for (auto i = ctx.objFileInstances.begin(), e = ctx.objFileInstances.end();
Rui Ueyama136d27a2019-07-11 05:40:302674 i != e; i++) {
2675 ObjFile *file = *i;
2676 if (isCrtend(file->getName())) {
Amy Huang6f7483b2021-09-16 23:48:262677 ctx.objFileInstances.erase(i);
2678 ctx.objFileInstances.push_back(file);
Martin Storsjocdf126e2019-04-15 10:57:442679 break;
2680 }
2681 }
2682 }
2683
Rui Ueyama151d8622015-06-17 20:40:432684 // Windows specific -- when we are creating a .dll file, we also
Martin Storsjo6540e552019-08-20 10:14:542685 // need to create a .lib file. In MinGW mode, we only do that when the
2686 // -implib option is given explicitly, for compatibility with GNU ld.
Jacek Cabane902cf22025-01-29 08:57:112687 if (config->dll || !ctx.symtab.exports.empty() ||
2688 (ctx.hybridSymtab && !ctx.hybridSymtab->exports.empty())) {
Alexandre Ganea356139b2023-10-06 02:33:582689 llvm::TimeTraceScope timeScope("Create .lib exports");
Jacek Caban455b3d62025-01-21 09:41:152690 ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });
Tobias Hietaeb4eef92022-04-12 14:06:462691 if (!config->noimplib && (!config->mingw || !config->implib.empty()))
Martin Storsjo6540e552019-08-20 10:14:542692 createImportLibrary(/*asLib=*/false);
Jacek Caban455b3d62025-01-21 09:41:152693 ctx.forEachSymtab(
2694 [](SymbolTable &symtab) { symtab.assignExportOrdinals(); });
Rui Ueyama8765fba2015-07-15 22:21:082695 }
Rui Ueyama97dff9e2015-06-17 00:16:332696
Martin Storsjo7f71acd2017-10-12 05:37:132697 // Handle /output-def (MinGW specific).
Rui Ueyama136d27a2019-07-11 05:40:302698 if (auto *arg = args.getLastArg(OPT_output_def))
Jacek Caban1c05c612025-04-11 13:53:252699 writeDefFile(ctx, arg->getValue(), ctx.symtab.exports);
Rui Ueyamad73479b2018-01-29 19:55:552700
Martin Storsjod2752aa2017-08-14 19:07:272701 // Set extra alignment for .comm symbols
Jacek Cabanf2473bc2025-03-03 21:48:202702 ctx.forEachSymtab([&](SymbolTable &symtab) {
2703 for (auto pair : symtab.alignComm) {
2704 StringRef name = pair.first;
2705 uint32_t alignment = pair.second;
Rui Ueyamacfc2f802017-09-13 21:54:552706
Jacek Cabanf2473bc2025-03-03 21:48:202707 Symbol *sym = symtab.find(name);
2708 if (!sym) {
2709 Warn(ctx) << "/aligncomm symbol " << name << " not found";
2710 continue;
2711 }
2712
2713 // If the symbol isn't common, it must have been replaced with a regular
2714 // symbol, which will carry its own alignment.
2715 auto *dc = dyn_cast<DefinedCommon>(sym);
2716 if (!dc)
2717 continue;
2718
2719 CommonChunk *c = dc->getChunk();
2720 c->setAlignment(std::max(c->getAlignment(), alignment));
Martin Storsjod2752aa2017-08-14 19:07:272721 }
Jacek Cabanf2473bc2025-03-03 21:48:202722 });
Martin Storsjod2752aa2017-08-14 19:07:272723
Nico Weber400a1de2021-08-24 14:19:212724 // Windows specific -- Create an embedded or side-by-side manifest.
2725 // /manifestdependency: enables /manifest unless an explicit /manifest:no is
2726 // also passed.
2727 if (config->manifest == Configuration::Embed)
2728 addBuffer(createManifestRes(), false, false);
2729 else if (config->manifest == Configuration::SideBySide ||
2730 (config->manifest == Configuration::Default &&
2731 !config->manifestDependencies.empty()))
Rafael Espindolab835ae82015-08-06 14:58:502732 createSideBySideManifest();
Rui Ueyama24c5fd02015-06-18 00:12:422733
Rui Ueyamab6d3a932018-01-29 21:50:532734 // Handle /order. We want to do this at this moment because we
2735 // need a complete list of comdat sections to warn on nonexistent
2736 // functions.
Zequan Wu763671f2020-07-21 20:46:112737 if (auto *arg = args.getLastArg(OPT_order)) {
2738 if (args.hasArg(OPT_call_graph_ordering_file))
Fangrui Song8d225f12024-12-06 03:44:262739 Err(ctx) << "/order and /call-graph-order-file may not be used together";
Amy Huang5a58b192023-01-10 04:37:282740 parseOrderFile(arg->getValue());
Zequan Wu763671f2020-07-21 20:46:112741 config->callGraphProfileSort = false;
2742 }
2743
2744 // Handle /call-graph-ordering-file and /call-graph-profile-sort (default on).
2745 if (config->callGraphProfileSort) {
Alexandre Ganea356139b2023-10-06 02:33:582746 llvm::TimeTraceScope timeScope("Call graph");
Haohai Wen2d9d2912025-01-05 02:38:142747 if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file))
Amy Huang5a58b192023-01-10 04:37:282748 parseCallGraphFile(arg->getValue());
Haohai Wen2d9d2912025-01-05 02:38:142749 else
2750 readCallGraphsFromObjectFiles(ctx);
Zequan Wu763671f2020-07-21 20:46:112751 }
2752
2753 // Handle /print-symbol-order.
2754 if (auto *arg = args.getLastArg(OPT_print_symbol_order))
2755 config->printSymbolOrder = arg->getValue();
Rui Ueyamab6d3a932018-01-29 21:50:532756
Jacek Caban61f80db2025-04-11 16:50:162757 if (ctx.symtab.isEC())
2758 ctx.symtab.initializeECThunks();
Jacek Cabanff29f382024-12-29 10:43:452759 ctx.forEachSymtab([](SymbolTable &symtab) { symtab.initializeLoadConfig(); });
Jacek Cabanfed8e382024-06-18 09:14:012760
Rui Ueyamaa5f0f752015-09-19 21:36:282761 // Identify unreferenced COMDAT sections.
Martin Storsjö7e076832021-05-09 20:27:352762 if (config->doGC) {
2763 if (config->mingw) {
2764 // markLive doesn't traverse .eh_frame, but the personality function is
2765 // only reached that way. The proper solution would be to parse and
2766 // traverse the .eh_frame section, like the ELF linker does.
2767 // For now, just manually try to retain the known possible personality
2768 // functions. This doesn't bring in more object files, but only marks
2769 // functions that already have been included to be retained.
Jacek Caband403f332025-03-02 12:37:512770 ctx.forEachSymtab([&](SymbolTable &symtab) {
2771 for (const char *n : {"__gxx_personality_v0", "__gcc_personality_v0",
2772 "rust_eh_personality"}) {
2773 Defined *d = dyn_cast_or_null<Defined>(symtab.findUnderscore(n));
2774 if (d && !d->isGCRoot) {
2775 d->isGCRoot = true;
2776 config->gcroot.push_back(d);
2777 }
Martin Storsjö7e076832021-05-09 20:27:352778 }
Jacek Caband403f332025-03-02 12:37:512779 });
Martin Storsjö7e076832021-05-09 20:27:352780 }
2781
Amy Huang6f7483b2021-09-16 23:48:262782 markLive(ctx);
Martin Storsjö7e076832021-05-09 20:27:352783 }
Rui Ueyamaa5f0f752015-09-19 21:36:282784
Nico Weberaf6bc652019-06-11 15:22:282785 // Needs to happen after the last call to addFile().
Martin Storsjo3d3a9b32019-08-30 06:56:332786 convertResources();
Nico Weberaf6bc652019-06-11 15:22:282787
Rui Ueyamaa5f0f752015-09-19 21:36:282788 // Identify identical COMDAT sections to merge them.
Zequan Wu5bdc5e72021-02-27 00:38:242789 if (config->doICF != ICFLevel::None) {
Amy Huang6f7483b2021-09-16 23:48:262790 findKeepUniqueSections(ctx);
Amy Huang5a58b192023-01-10 04:37:282791 doICF(ctx);
Peter Collingbourneab038022018-08-23 17:44:422792 }
Rui Ueyamaa5f0f752015-09-19 21:36:282793
Rui Ueyama411c63602015-05-28 19:09:302794 // Write the result.
Amy Huang6f7483b2021-09-16 23:48:262795 writeResult(ctx);
Zachary Turner727f1532018-01-17 19:16:262796
2797 // Stop early so we can print the results.
Reid Kleckner3508c1d2020-05-20 14:50:192798 rootTimer.stop();
Rui Ueyama136d27a2019-07-11 05:40:302799 if (config->showTiming)
Amy Huang6f7483b2021-09-16 23:48:262800 ctx.rootTimer.print();
Alexandre Ganea356139b2023-10-06 02:33:582801
2802 if (config->timeTraceEnabled) {
2803 // Manually stop the topmost "COFF link" scope, since we're shutting down.
2804 timeTraceProfilerEnd();
2805
2806 checkError(timeTraceProfilerWrite(
2807 args.getLastArgValue(OPT_time_trace_eq).str(), config->outputFile));
2808 timeTraceProfilerCleanup();
2809 }
Rui Ueyama411c63602015-05-28 19:09:302810}
2811
Nico Weber7c266412022-08-08 15:32:262812} // namespace lld::coff