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