1 //===- lld/ReaderWriter/PECOFFLinkingContext.h ----------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLD_READER_WRITER_PECOFF_LINKING_CONTEXT_H
11 #define LLD_READER_WRITER_PECOFF_LINKING_CONTEXT_H
13 #include "lld/Core/LinkingContext.h"
14 #include "lld/Core/Reader.h"
15 #include "lld/Core/Writer.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/Support/Allocator.h"
18 #include "llvm/Support/COFF.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/FileUtilities.h"
26 using llvm::COFF::MachineTypes;
27 using llvm::COFF::WindowsSubsystem;
29 static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};
33 class PECOFFLinkingContext : public LinkingContext {
35 PECOFFLinkingContext()
36 : _mutex(), _allocMutex(), _hasEntry(true),
37 _baseAddress(invalidBaseAddress), _stackReserve(1024 * 1024),
38 _stackCommit(4096), _heapReserve(1024 * 1024), _heapCommit(4096),
39 _noDefaultLibAll(false), _sectionDefaultAlignment(4096),
40 _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
41 _machineType(llvm::COFF::IMAGE_FILE_MACHINE_I386), _imageVersion(0, 0),
42 _minOSVersion(6, 0), _nxCompat(true), _largeAddressAware(false),
43 _allowBind(true), _allowIsolation(true), _swapRunFromCD(false),
44 _swapRunFromNet(false), _baseRelocationEnabled(true),
45 _terminalServerAware(true), _dynamicBaseEnabled(true),
46 _createManifest(true), _embedManifest(false), _manifestId(1),
47 _manifestUAC(true), _manifestLevel("'asInvoker'"),
48 _manifestUiAccess("'false'"), _isDll(false), _highEntropyVA(true),
49 _requireSEH(false), _noSEH(false), _implib(""), _debug(false),
50 _pdbFilePath(""), _dosStub(llvm::makeArrayRef(DEFAULT_DOS_STUB)),
51 _parseDirectives(nullptr) {
52 setDeadStripping(true);
56 Version(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
63 : ordinal(-1), noname(false), isData(false), isPrivate(false) {}
65 bool operator<(const ExportDesc &other) const {
66 return getExternalName().compare(other.getExternalName()) < 0;
69 StringRef getRealName() const {
70 return mangledName.empty() ? name : mangledName;
73 StringRef getExternalName() const {
74 return externalName.empty() ? name : externalName;
78 std::string externalName;
79 std::string mangledName;
86 typedef bool (*ParseDirectives)(int, const char **, PECOFFLinkingContext &,
89 /// \brief Casting support
90 static bool classof(const LinkingContext *info) { return true; }
92 Writer &writer() const override;
93 bool validateImpl(raw_ostream &diagnostics) override;
95 void addPasses(PassManager &pm) override;
97 bool createImplicitFiles(
98 std::vector<std::unique_ptr<File> > &result) override;
100 bool is64Bit() const {
101 return _machineType == llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
104 // Returns a set of all defined symbols in input files.
105 const std::set<std::string> &definedSymbols();
107 /// Page size of x86 processor. Some data needs to be aligned at page boundary
108 /// when loaded into memory.
109 uint64_t getPageSize() const {
113 void appendInputSearchPath(StringRef dirPath) {
114 _inputSearchPaths.push_back(dirPath);
117 const std::vector<StringRef> getInputSearchPaths() {
118 return _inputSearchPaths;
121 void registerTemporaryFile(StringRef path) {
122 std::unique_ptr<llvm::FileRemover> fileRemover(
123 new llvm::FileRemover(Twine(allocate(path))));
124 _tempFiles.push_back(std::move(fileRemover));
127 StringRef searchLibraryFile(StringRef path) const;
129 StringRef decorateSymbol(StringRef name) const;
130 StringRef undecorateSymbol(StringRef name) const;
132 void setEntrySymbolName(StringRef name) { _entry = name; }
133 StringRef getEntrySymbolName() const { return _entry; }
135 void setHasEntry(bool val) { _hasEntry = val; }
136 bool hasEntry() const { return _hasEntry; }
138 void setBaseAddress(uint64_t addr) { _baseAddress = addr; }
139 uint64_t getBaseAddress() const;
141 void setStackReserve(uint64_t size) { _stackReserve = size; }
142 void setStackCommit(uint64_t size) { _stackCommit = size; }
143 uint64_t getStackReserve() const { return _stackReserve; }
144 uint64_t getStackCommit() const { return _stackCommit; }
146 void setHeapReserve(uint64_t size) { _heapReserve = size; }
147 void setHeapCommit(uint64_t size) { _heapCommit = size; }
148 uint64_t getHeapReserve() const { return _heapReserve; }
149 uint64_t getHeapCommit() const { return _heapCommit; }
151 void setSectionDefaultAlignment(uint32_t val) {
152 _sectionDefaultAlignment = val;
154 uint32_t getSectionDefaultAlignment() const {
155 return _sectionDefaultAlignment;
158 void setSubsystem(WindowsSubsystem ss) { _subsystem = ss; }
159 WindowsSubsystem getSubsystem() const { return _subsystem; }
161 void setMachineType(MachineTypes type) { _machineType = type; }
162 MachineTypes getMachineType() const { return _machineType; }
164 void setImageVersion(const Version &version) { _imageVersion = version; }
165 Version getImageVersion() const { return _imageVersion; }
167 void setMinOSVersion(const Version &version) { _minOSVersion = version; }
168 Version getMinOSVersion() const { return _minOSVersion; }
170 void setNxCompat(bool nxCompat) { _nxCompat = nxCompat; }
171 bool isNxCompat() const { return _nxCompat; }
173 void setLargeAddressAware(bool val) { _largeAddressAware = val; }
174 bool getLargeAddressAware() const { return _largeAddressAware; }
176 void setAllowBind(bool val) { _allowBind = val; }
177 bool getAllowBind() const { return _allowBind; }
179 void setAllowIsolation(bool val) { _allowIsolation = val; }
180 bool getAllowIsolation() const { return _allowIsolation; }
182 void setSwapRunFromCD(bool val) { _swapRunFromCD = val; }
183 bool getSwapRunFromCD() const { return _swapRunFromCD; }
185 void setSwapRunFromNet(bool val) { _swapRunFromNet = val; }
186 bool getSwapRunFromNet() const { return _swapRunFromNet; }
188 void setBaseRelocationEnabled(bool val) { _baseRelocationEnabled = val; }
189 bool getBaseRelocationEnabled() const { return _baseRelocationEnabled; }
191 void setTerminalServerAware(bool val) { _terminalServerAware = val; }
192 bool isTerminalServerAware() const { return _terminalServerAware; }
194 void setDynamicBaseEnabled(bool val) { _dynamicBaseEnabled = val; }
195 bool getDynamicBaseEnabled() const { return _dynamicBaseEnabled; }
197 void setCreateManifest(bool val) { _createManifest = val; }
198 bool getCreateManifest() const { return _createManifest; }
200 void setManifestOutputPath(std::string val) { _manifestOutputPath = val; }
201 const std::string &getManifestOutputPath() const {
202 return _manifestOutputPath;
205 void setEmbedManifest(bool val) { _embedManifest = val; }
206 bool getEmbedManifest() const { return _embedManifest; }
208 void setManifestId(int val) { _manifestId = val; }
209 int getManifestId() const { return _manifestId; }
211 void setManifestUAC(bool val) { _manifestUAC = val; }
212 bool getManifestUAC() const { return _manifestUAC; }
214 void setManifestLevel(std::string val) { _manifestLevel = std::move(val); }
215 const std::string &getManifestLevel() const { return _manifestLevel; }
217 void setManifestUiAccess(std::string val) { _manifestUiAccess = val; }
218 const std::string &getManifestUiAccess() const { return _manifestUiAccess; }
220 void setManifestDependency(std::string val) { _manifestDependency = val; }
221 const std::string &getManifestDependency() const {
222 return _manifestDependency;
225 void setIsDll(bool val) { _isDll = val; }
226 bool isDll() const { return _isDll; }
228 void setSafeSEH(bool val) {
234 bool requireSEH() const { return _requireSEH; }
235 bool noSEH() const { return _noSEH; }
237 void setHighEntropyVA(bool val) { _highEntropyVA = val; }
238 bool getHighEntropyVA() const { return _highEntropyVA; }
240 void setOutputImportLibraryPath(const std::string &val) { _implib = val; }
241 std::string getOutputImportLibraryPath() const;
243 void setDebug(bool val) { _debug = val; }
244 bool getDebug() { return _debug; }
246 void setPDBFilePath(StringRef str) { _pdbFilePath = str; }
247 std::string getPDBFilePath() const;
249 void addDelayLoadDLL(StringRef dll) {
250 _delayLoadDLLs.insert(dll.lower());
252 bool isDelayLoadDLL(StringRef dll) const {
253 return _delayLoadDLLs.count(dll.lower()) == 1;
256 StringRef getOutputSectionName(StringRef sectionName) const;
257 bool addSectionRenaming(raw_ostream &diagnostics,
258 StringRef from, StringRef to);
260 const std::set<std::string> &getAlternateNames(StringRef name) {
261 return _alternateNames[name];
264 void addAlternateName(StringRef weak, StringRef def) {
265 _alternateNames[def].insert(weak);
268 void addNoDefaultLib(StringRef path) {
269 if (path.endswith_lower(".lib"))
270 _noDefaultLibs.insert(path.drop_back(4).lower());
272 _noDefaultLibs.insert(path.lower());
275 bool hasNoDefaultLib(StringRef path) const {
276 if (path.endswith_lower(".lib"))
277 return _noDefaultLibs.count(path.drop_back(4).lower()) > 0;
278 return _noDefaultLibs.count(path.lower()) > 0;
281 void setNoDefaultLibAll(bool val) { _noDefaultLibAll = val; }
282 bool getNoDefaultLibAll() const { return _noDefaultLibAll; }
284 void setSectionSetMask(StringRef sectionName, uint32_t flags);
285 void setSectionClearMask(StringRef sectionName, uint32_t flags);
286 uint32_t getSectionAttributes(StringRef sectionName, uint32_t flags) const;
288 void setDosStub(ArrayRef<uint8_t> data) { _dosStub = data; }
289 ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
291 void addDllExport(ExportDesc &desc);
292 std::vector<ExportDesc> &getDllExports() { return _dllExports; }
293 const std::vector<ExportDesc> &getDllExports() const { return _dllExports; }
295 StringRef getDelayLoadHelperName() const {
296 return is64Bit() ? "__delayLoadHelper2" : "___delayLoadHelper2@8";
299 StringRef allocate(StringRef ref) const {
301 char *x = _allocator.Allocate<char>(ref.size() + 1);
302 _allocMutex.unlock();
303 memcpy(x, ref.data(), ref.size());
304 x[ref.size()] = '\0';
308 ArrayRef<uint8_t> allocate(ArrayRef<uint8_t> array) const {
309 size_t size = array.size();
311 uint8_t *p = _allocator.Allocate<uint8_t>(size);
312 _allocMutex.unlock();
313 memcpy(p, array.data(), size);
314 return ArrayRef<uint8_t>(p, p + array.size());
317 template <typename T> T &allocateCopy(const T &x) const {
319 T *r = new (_allocator) T(x);
320 _allocMutex.unlock();
324 void addLibraryFile(std::unique_ptr<FileNode> file);
326 void setModuleDefinitionFile(const std::string val) {
327 _moduleDefinitionFile = val;
329 std::string getModuleDefinitionFile() const {
330 return _moduleDefinitionFile;
333 std::recursive_mutex &getMutex() { return _mutex; }
335 void setParseDirectives(ParseDirectives parseDirectives) {
336 _parseDirectives = parseDirectives;
339 ParseDirectives getParseDirectives() {
340 return _parseDirectives;
344 /// Method to create a internal file for the entry symbol
345 std::unique_ptr<File> createEntrySymbolFile() const override;
347 /// Method to create a internal file for an undefined symbol
348 std::unique_ptr<File> createUndefinedSymbolFile() const override;
352 invalidBaseAddress = UINT64_MAX,
353 pe32DefaultBaseAddress = 0x400000U,
354 pe32PlusDefaultBaseAddress = 0x140000000U
357 std::recursive_mutex _mutex;
358 mutable std::mutex _allocMutex;
362 // False if /noentry option is given.
365 // The start address for the program. The default value for the executable is
366 // 0x400000, but can be altered using /base command line option.
367 uint64_t _baseAddress;
369 uint64_t _stackReserve;
370 uint64_t _stackCommit;
371 uint64_t _heapReserve;
372 uint64_t _heapCommit;
373 bool _noDefaultLibAll;
374 uint32_t _sectionDefaultAlignment;
375 WindowsSubsystem _subsystem;
376 MachineTypes _machineType;
377 Version _imageVersion;
378 Version _minOSVersion;
380 bool _largeAddressAware;
382 bool _allowIsolation;
384 bool _swapRunFromNet;
385 bool _baseRelocationEnabled;
386 bool _terminalServerAware;
387 bool _dynamicBaseEnabled;
388 bool _createManifest;
389 std::string _manifestOutputPath;
393 std::string _manifestLevel;
394 std::string _manifestUiAccess;
395 std::string _manifestDependency;
399 // True if /SAFESEH option is specified. Valid only for x86. If true, LLD will
400 // produce an image with SEH table. If any modules were not compatible with
401 // SEH, LLD will exit with an error.
404 // True if /SAFESEH:no option is specified. Valid only for x86. If true, LLD
405 // will not produce an image with SEH table even if all input object files are
406 // compatible with SEH.
409 // /IMPLIB command line option.
412 // True if /DEBUG is given.
415 // PDB file output path. NB: this is dummy -- LLD just creates the empty file.
416 std::string _pdbFilePath;
418 // /DELAYLOAD option.
419 std::set<std::string> _delayLoadDLLs;
421 // The set to store /nodefaultlib arguments.
422 std::set<std::string> _noDefaultLibs;
424 std::vector<StringRef> _inputSearchPaths;
425 std::unique_ptr<Writer> _writer;
427 // A map for weak aliases.
428 std::map<std::string, std::set<std::string>> _alternateNames;
430 // A map for section renaming. For example, if there is an entry in the map
431 // whose value is .rdata -> .text, the section contens of .rdata will be
432 // merged to .text in the resulting executable.
433 std::map<std::string, std::string> _renamedSections;
435 // Section attributes specified by /section option.
436 std::map<std::string, uint32_t> _sectionSetMask;
437 std::map<std::string, uint32_t> _sectionClearMask;
439 // DLLExport'ed symbols.
440 std::vector<ExportDesc> _dllExports;
442 // List of files that will be removed on destruction.
443 std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;
445 // DOS Stub. DOS stub is data located at the beginning of PE/COFF file.
446 // Windows loader do not really care about DOS stub contents, but it's usually
447 // a small DOS program that prints out a message "This program requires
448 // Microsoft Windows." This feature was somewhat useful before Windows 95.
449 ArrayRef<uint8_t> _dosStub;
451 // Name of the temporary file for lib.exe subcommand. For debugging
453 std::string _moduleDefinitionFile;
455 std::set<std::string> _definedSyms;
456 std::set<Node *> _seen;
458 ParseDirectives _parseDirectives;
461 } // end namespace lld