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