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 }; 116 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 /opt:[no]ltodebugpassmanager 196 bool ltoDebugPassManager = false; 197 198 // Used for /merge:from=to (e.g. /merge:.rdata=.text) 199 std::map<StringRef, StringRef> merge; 200 201 // Used for /section=.name,{DEKPRSW} to set section attributes. 202 std::map<StringRef, uint32_t> section; 203 204 // Options for manifest files. 205 ManifestKind manifest = Default; 206 int manifestID = 1; 207 llvm::SetVector<StringRef> manifestDependencies; 208 bool manifestUAC = true; 209 std::vector<std::string> manifestInput; 210 StringRef manifestLevel = "'asInvoker'"; 211 StringRef manifestUIAccess = "'false'"; 212 StringRef manifestFile; 213 214 // used for /dwodir 215 StringRef dwoDir; 216 217 // Used for /aligncomm. 218 std::map<std::string, int> alignComm; 219 220 // Used for /failifmismatch. 221 std::map<StringRef, std::pair<StringRef, InputFile *>> mustMatch; 222 223 // Used for /alternatename. 224 std::map<StringRef, StringRef> alternateNames; 225 226 // Used for /order. 227 llvm::StringMap<int> order; 228 229 // Used for /lldmap. 230 std::string lldmapFile; 231 232 // Used for /map. 233 std::string mapFile; 234 235 // Used for /mapinfo. 236 bool mapInfo = false; 237 238 // Used for /thinlto-index-only: 239 llvm::StringRef thinLTOIndexOnlyArg; 240 241 // Used for /thinlto-prefix-replace: 242 // Replace the prefix in paths generated for ThinLTO, replacing 243 // thinLTOPrefixReplaceOld with thinLTOPrefixReplaceNew. If 244 // thinLTOPrefixReplaceNativeObject is defined, replace the prefix of object 245 // file paths written to the response file given in the 246 // --thinlto-index-only=${response} option with 247 // thinLTOPrefixReplaceNativeObject, instead of thinLTOPrefixReplaceNew. 248 llvm::StringRef thinLTOPrefixReplaceOld; 249 llvm::StringRef thinLTOPrefixReplaceNew; 250 llvm::StringRef thinLTOPrefixReplaceNativeObject; 251 252 // Used for /thinlto-object-suffix-replace: 253 std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace; 254 255 // Used for /lto-obj-path: 256 llvm::StringRef ltoObjPath; 257 258 // Used for /lto-cs-profile-generate: 259 bool ltoCSProfileGenerate = false; 260 261 // Used for /lto-cs-profile-path 262 llvm::StringRef ltoCSProfileFile; 263 264 // Used for /lto-pgo-warn-mismatch: 265 bool ltoPGOWarnMismatch = true; 266 267 // Used for /lto-sample-profile: 268 llvm::StringRef ltoSampleProfileName; 269 270 // Used for /call-graph-ordering-file: 271 llvm::MapVector<std::pair<const SectionChunk *, const SectionChunk *>, 272 uint64_t> 273 callGraphProfile; 274 bool callGraphProfileSort = false; 275 276 // Used for /print-symbol-order: 277 StringRef printSymbolOrder; 278 279 // Used for /vfsoverlay: 280 std::unique_ptr<llvm::vfs::FileSystem> vfs; 281 282 uint64_t align = 4096; 283 uint64_t imageBase = -1; 284 uint64_t fileAlign = 512; 285 uint64_t stackReserve = 1024 * 1024; 286 uint64_t stackCommit = 4096; 287 uint64_t heapReserve = 1024 * 1024; 288 uint64_t heapCommit = 4096; 289 uint32_t majorImageVersion = 0; 290 uint32_t minorImageVersion = 0; 291 // If changing the default os/subsys version here, update the default in 292 // the MinGW driver accordingly. 293 uint32_t majorOSVersion = 6; 294 uint32_t minorOSVersion = 0; 295 uint32_t majorSubsystemVersion = 6; 296 uint32_t minorSubsystemVersion = 0; 297 uint32_t timestamp = 0; 298 uint32_t functionPadMin = 0; 299 uint32_t timeTraceGranularity = 0; 300 uint16_t dependentLoadFlags = 0; 301 bool dynamicBase = true; 302 bool allowBind = true; 303 bool cetCompat = false; 304 bool nxCompat = true; 305 bool allowIsolation = true; 306 bool terminalServerAware = true; 307 bool largeAddressAware = false; 308 bool highEntropyVA = false; 309 bool appContainer = false; 310 bool mingw = false; 311 bool warnMissingOrderSymbol = true; 312 bool warnLocallyDefinedImported = true; 313 bool warnDebugInfoUnusable = true; 314 bool warnLongSectionNames = true; 315 bool warnStdcallFixup = true; 316 bool incremental = true; 317 bool integrityCheck = false; 318 bool killAt = false; 319 bool repro = false; 320 bool swaprunCD = false; 321 bool swaprunNet = false; 322 bool thinLTOEmitImportsFiles; 323 bool thinLTOIndexOnly; 324 bool timeTraceEnabled = false; 325 bool autoImport = false; 326 bool pseudoRelocs = false; 327 bool stdcallFixup = false; 328 bool writeCheckSum = false; 329 EmitKind emit = EmitKind::Obj; 330 bool allowDuplicateWeak = false; 331 BuildIDHash buildIDHash = BuildIDHash::None; 332 }; 333 334 struct COFFSyncStream : SyncStream { 335 COFFLinkerContext &ctx; 336 COFFSyncStream(COFFLinkerContext &ctx, DiagLevel level); 337 }; 338 339 template <typename T> 340 std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>, 341 const COFFSyncStream &> 342 operator<<(const COFFSyncStream &s, T &&v) { 343 s.os << std::forward<T>(v); 344 return s; 345 } 346 347 inline const COFFSyncStream &operator<<(const COFFSyncStream &s, 348 const char *v) { 349 s.os << v; 350 return s; 351 } 352 353 inline const COFFSyncStream &operator<<(const COFFSyncStream &s, Error v) { 354 s.os << llvm::toString(std::move(v)); 355 return s; 356 } 357 358 // Report a log if -verbose is specified. 359 COFFSyncStream Log(COFFLinkerContext &ctx); 360 361 // Print a message to stdout. 362 COFFSyncStream Msg(COFFLinkerContext &ctx); 363 364 // Report a warning. Upgraded to an error if /WX is specified. 365 COFFSyncStream Warn(COFFLinkerContext &ctx); 366 367 // Report an error that will suppress the output file generation. 368 COFFSyncStream Err(COFFLinkerContext &ctx); 369 370 // Report a fatal error that exits immediately. This should generally be avoided 371 // in favor of Err. 372 COFFSyncStream Fatal(COFFLinkerContext &ctx); 373 374 uint64_t errCount(COFFLinkerContext &ctx); 375 376 } // namespace lld::coff 377 378 #endif 379