1//===- Config.h -------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_COFF_CONFIG_H
10#define LLD_COFF_CONFIG_H
11
12#include "lld/Common/ErrorHandler.h"
13#include "llvm/ADT/MapVector.h"
14#include "llvm/ADT/SetVector.h"
15#include "llvm/ADT/SmallVector.h"
16#include "llvm/ADT/StringMap.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/StringSet.h"
19#include "llvm/Object/COFF.h"
20#include "llvm/Support/CachePruning.h"
21#include "llvm/Support/VirtualFileSystem.h"
22#include <cstdint>
23#include <map>
24#include <optional>
25#include <string>
26
27namespace lld::coff {
28
29using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
30using llvm::COFF::WindowsSubsystem;
31using llvm::StringRef;
32class COFFLinkerContext;
33class DefinedAbsolute;
34class StringChunk;
35class Symbol;
36class InputFile;
37class SectionChunk;
38
39// Short aliases.
40static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
41static const auto ARM64 = llvm::COFF::IMAGE_FILE_MACHINE_ARM64;
42static const auto ARM64EC = llvm::COFF::IMAGE_FILE_MACHINE_ARM64EC;
43static const auto ARM64X = llvm::COFF::IMAGE_FILE_MACHINE_ARM64X;
44static const auto ARMNT = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
45static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;
46
47enum class ExportSource {
48 Unset,
49 Directives,
50 Export,
51 ModuleDefinition,
52 ExportAll,
53};
54
55enum class EmitKind { Obj, LLVM, ASM };
56
57// Represents an /export option.
58struct Export {
59 StringRef name; // N in /export:N or /export:E=N
60 StringRef extName; // E in /export:E=N
61 StringRef exportAs; // E in /export:N,EXPORTAS,E
62 StringRef importName; // GNU specific: N in "othername == N"
63 Symbol *sym = nullptr;
64 uint16_t ordinal = 0;
65 bool noname = false;
66 bool data = false;
67 bool isPrivate = false;
68 bool constant = false;
69
70 // If an export is a form of /export:foo=dllname.bar, that means
71 // that foo should be exported as an alias to bar in the DLL.
72 // forwardTo is set to "dllname.bar" part. Usually empty.
73 StringRef forwardTo;
74 StringChunk *forwardChunk = nullptr;
75
76 ExportSource source = ExportSource::Unset;
77 StringRef symbolName;
78 StringRef exportName; // Name in DLL
79
80 bool operator==(const Export &e) const {
81 return (name == e.name && extName == e.extName && exportAs == e.exportAs &&
82 importName == e.importName && ordinal == e.ordinal &&
83 noname == e.noname && data == e.data && isPrivate == e.isPrivate);
84 }
85};
86
87enum class DebugType {
88 None = 0x0,
89 CV = 0x1, /// CodeView
90 PData = 0x2, /// Procedure Data
91 Fixup = 0x4, /// Relocation Table
92};
93
94enum GuardCFLevel {
95 Off = 0x0,
96 CF = 0x1, /// Emit gfids tables
97 LongJmp = 0x2, /// Emit longjmp tables
98 EHCont = 0x4, /// Emit ehcont tables
99 All = 0x7 /// Enable all protections
100};
101
102enum class ICFLevel {
103 None,
104 Safe, // Safe ICF for all sections.
105 All, // Aggressive ICF for code, but safe ICF for data, similar to MSVC's
106 // behavior.
107};
108
109enum class BuildIDHash {
110 None,
111 PDB,
112 Binary,
113};
114
115// Global configuration.
116struct Configuration {
117 enum ManifestKind { Default, SideBySide, Embed, No };
118 bool is64() const { return llvm::COFF::is64Bit(Machine: machine); }
119
120 std::unique_ptr<MemoryBuffer> dosStub;
121 llvm::COFF::MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN;
122 bool machineInferred = false;
123 size_t wordsize;
124 bool verbose = false;
125 WindowsSubsystem subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
126 bool noEntry = false;
127 std::string outputFile;
128 std::string importName;
129 bool demangle = true;
130 bool doGC = true;
131 ICFLevel doICF = ICFLevel::None;
132 bool tailMerge;
133 bool relocatable = true;
134 bool forceMultiple = false;
135 bool forceMultipleRes = false;
136 bool forceUnresolved = false;
137 bool debug = false;
138 bool includeDwarfChunks = false;
139 bool debugGHashes = false;
140 bool writeSymtab = false;
141 bool driver = false;
142 bool driverUponly = false;
143 bool driverWdm = false;
144 bool showTiming = false;
145 bool showSummary = false;
146 bool printSearchPaths = false;
147 unsigned debugTypes = static_cast<unsigned>(DebugType::None);
148 llvm::SmallVector<llvm::StringRef, 0> mllvmOpts;
149 std::vector<std::string> natvisFiles;
150 llvm::StringMap<std::string> namedStreams;
151 llvm::SmallString<128> pdbAltPath;
152 int pdbPageSize = 4096;
153 llvm::SmallString<128> pdbPath;
154 llvm::SmallString<128> pdbSourcePath;
155 std::vector<llvm::StringRef> argv;
156
157 // Symbols in this set are considered as live by the garbage collector.
158 std::vector<Symbol *> gcroot;
159
160 llvm::StringSet<> noDefaultLibs;
161 bool noDefaultLibAll = false;
162
163 // True if we are creating a DLL.
164 bool dll = false;
165 StringRef implib;
166 bool noimplib = false;
167 llvm::StringSet<> delayLoads;
168 std::map<std::string, int> dllOrder;
169 Symbol *arm64ECIcallHelper = nullptr;
170
171 llvm::DenseSet<llvm::StringRef> saveTempsArgs;
172
173 // /guard:cf
174 int guardCF = GuardCFLevel::Off;
175
176 // Used for SafeSEH.
177 bool safeSEH = false;
178 Symbol *sehTable = nullptr;
179 Symbol *sehCount = nullptr;
180 bool noSEH = false;
181
182 // Used for /opt:lldlto=N
183 unsigned ltoo = 2;
184 // Used for /opt:lldltocgo=N
185 std::optional<unsigned> ltoCgo;
186
187 // Used for /opt:lldltojobs=N
188 std::string thinLTOJobs;
189 // Used for /opt:lldltopartitions=N
190 unsigned ltoPartitions = 1;
191
192 // Used for /lldltocache=path
193 StringRef ltoCache;
194 // Used for /lldltocachepolicy=policy
195 llvm::CachePruningPolicy ltoCachePolicy;
196
197 // Used for /thinlto-distributor:<path>
198 StringRef dtltoDistributor;
199
200 // Used for /thinlto-distributor-arg:<arg>
201 llvm::SmallVector<llvm::StringRef, 0> dtltoDistributorArgs;
202
203 // Used for /thinlto-remote-compiler:<path>
204 StringRef dtltoCompiler;
205
206 // Used for /thinlto-remote-compiler-prepend-arg:<arg>
207 llvm::SmallVector<llvm::StringRef, 0> dtltoCompilerPrependArgs;
208
209 // Used for /thinlto-remote-compiler-arg:<arg>
210 llvm::SmallVector<llvm::StringRef, 0> dtltoCompilerArgs;
211
212 // Used for /fat-lto-objects
213 bool fatLTOObjects = false;
214
215 // Used for /opt:[no]ltodebugpassmanager
216 bool ltoDebugPassManager = false;
217
218 // Used for /merge:from=to (e.g. /merge:.rdata=.text)
219 std::map<StringRef, StringRef> merge;
220
221 // Used for /discard-section:.name
222 llvm::StringSet<> discardSection;
223
224 // Used for /section=.name,{DEKPRSW} to set section attributes.
225 std::map<StringRef, uint32_t> section;
226 // Used for /sectionlayout: to layout sections in specified order.
227 std::map<std::string, int> sectionOrder;
228
229 // Options for manifest files.
230 ManifestKind manifest = Default;
231 int manifestID = 1;
232 llvm::SetVector<StringRef> manifestDependencies;
233 bool manifestUAC = true;
234 std::vector<std::string> manifestInput;
235 StringRef manifestLevel = "'asInvoker'";
236 StringRef manifestUIAccess = "'false'";
237 StringRef manifestFile;
238
239 // used for /arm64xsameaddress
240 std::vector<std::pair<Symbol *, Symbol *>> sameAddresses;
241
242 // used for /dwodir
243 StringRef dwoDir;
244
245 // Used for /failifmismatch.
246 std::map<StringRef, std::pair<StringRef, InputFile *>> mustMatch;
247
248 // Used for /order.
249 llvm::StringMap<int> order;
250
251 // Used for /lldmap.
252 std::string lldmapFile;
253
254 // Used for /map.
255 std::string mapFile;
256
257 // Used for /mapinfo.
258 bool mapInfo = false;
259
260 // Used for /thinlto-index-only:
261 llvm::StringRef thinLTOIndexOnlyArg;
262
263 // Used for /thinlto-prefix-replace:
264 // Replace the prefix in paths generated for ThinLTO, replacing
265 // thinLTOPrefixReplaceOld with thinLTOPrefixReplaceNew. If
266 // thinLTOPrefixReplaceNativeObject is defined, replace the prefix of object
267 // file paths written to the response file given in the
268 // --thinlto-index-only=${response} option with
269 // thinLTOPrefixReplaceNativeObject, instead of thinLTOPrefixReplaceNew.
270 llvm::StringRef thinLTOPrefixReplaceOld;
271 llvm::StringRef thinLTOPrefixReplaceNew;
272 llvm::StringRef thinLTOPrefixReplaceNativeObject;
273
274 // Used for /thinlto-object-suffix-replace:
275 std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
276
277 // Used for /lto-obj-path:
278 llvm::StringRef ltoObjPath;
279
280 // Used for /lto-cs-profile-generate:
281 bool ltoCSProfileGenerate = false;
282
283 // Used for /lto-cs-profile-path
284 llvm::StringRef ltoCSProfileFile;
285
286 // Used for /lto-pgo-warn-mismatch:
287 bool ltoPGOWarnMismatch = true;
288
289 // Used for /lto-sample-profile:
290 llvm::StringRef ltoSampleProfileName;
291
292 // Used for /call-graph-ordering-file:
293 llvm::MapVector<std::pair<const SectionChunk *, const SectionChunk *>,
294 uint64_t>
295 callGraphProfile;
296 bool callGraphProfileSort = false;
297
298 // Used for /print-symbol-order:
299 StringRef printSymbolOrder;
300
301 // Used for /vfsoverlay:
302 std::unique_ptr<llvm::vfs::FileSystem> vfs;
303
304 uint64_t align = 4096;
305 uint64_t imageBase = -1;
306 uint64_t fileAlign = 512;
307 uint64_t stackReserve = 1024 * 1024;
308 uint64_t stackCommit = 4096;
309 uint64_t heapReserve = 1024 * 1024;
310 uint64_t heapCommit = 4096;
311 uint32_t majorImageVersion = 0;
312 uint32_t minorImageVersion = 0;
313 // If changing the default os/subsys version here, update the default in
314 // the MinGW driver accordingly.
315 uint32_t majorOSVersion = 6;
316 uint32_t minorOSVersion = 0;
317 uint32_t majorSubsystemVersion = 6;
318 uint32_t minorSubsystemVersion = 0;
319 uint32_t timestamp = 0;
320 uint32_t functionPadMin = 0;
321 uint32_t timeTraceGranularity = 0;
322 uint16_t dependentLoadFlags = 0;
323 bool dynamicBase = true;
324 bool allowBind = true;
325 bool cetCompat = false;
326 bool cetCompatStrict = false;
327 bool cetCompatIpValidationRelaxed = false;
328 bool cetCompatDynamicApisInProcOnly = false;
329 bool hotpatchCompat = false;
330 bool nxCompat = true;
331 bool allowIsolation = true;
332 bool terminalServerAware = true;
333 bool largeAddressAware = false;
334 bool highEntropyVA = false;
335 bool appContainer = false;
336 bool mergeDebugDirectory = true;
337 bool mingw = false;
338 bool warnMissingOrderSymbol = true;
339 bool warnLocallyDefinedImported = true;
340 bool warnDebugInfoUnusable = true;
341 bool warnLongSectionNames = true;
342 bool warnStdcallFixup = true;
343 bool warnImportedDllMain = true;
344 bool incremental = true;
345 bool integrityCheck = false;
346 bool killAt = false;
347 bool repro = false;
348 bool swaprunCD = false;
349 bool swaprunNet = false;
350 bool thinLTOEmitImportsFiles;
351 bool thinLTOIndexOnly;
352 bool timeTraceEnabled = false;
353 bool autoImport = false;
354 bool pseudoRelocs = false;
355 bool stdcallFixup = false;
356 bool writeCheckSum = false;
357 bool prefetchInputs = false;
358 EmitKind emit = EmitKind::Obj;
359 bool allowDuplicateWeak = false;
360 BuildIDHash buildIDHash = BuildIDHash::None;
361 llvm::StringRef optRemarksFilename;
362 llvm::StringRef optRemarksPasses;
363 llvm::StringRef optRemarksFormat;
364 bool optRemarksWithHotness = false;
365 std::optional<uint64_t> optRemarksHotnessThreshold = 0;
366};
367
368struct COFFSyncStream : SyncStream {
369 COFFLinkerContext &ctx;
370 COFFSyncStream(COFFLinkerContext &ctx, DiagLevel level);
371};
372
373template <typename T>
374std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>,
375 const COFFSyncStream &>
376operator<<(const COFFSyncStream &s, T &&v) {
377 s.os << std::forward<T>(v);
378 return s;
379}
380
381inline const COFFSyncStream &operator<<(const COFFSyncStream &s,
382 const char *v) {
383 s.os << v;
384 return s;
385}
386
387inline const COFFSyncStream &operator<<(const COFFSyncStream &s, Error v) {
388 s.os << llvm::toString(E: std::move(v));
389 return s;
390}
391
392// Report a log if -verbose is specified.
393COFFSyncStream Log(COFFLinkerContext &ctx);
394
395// Print a message to stdout.
396COFFSyncStream Msg(COFFLinkerContext &ctx);
397
398// Report a warning. Upgraded to an error if /WX is specified.
399COFFSyncStream Warn(COFFLinkerContext &ctx);
400
401// Report an error that will suppress the output file generation.
402COFFSyncStream Err(COFFLinkerContext &ctx);
403
404// Report a fatal error that exits immediately. This should generally be avoided
405// in favor of Err.
406COFFSyncStream Fatal(COFFLinkerContext &ctx);
407
408uint64_t errCount(COFFLinkerContext &ctx);
409
410} // namespace lld::coff
411
412#endif
413