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