]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - include/lld/ReaderWriter/PECOFFLinkingContext.h
Vendor import of lld trunk r233088:
[FreeBSD/FreeBSD.git] / include / lld / ReaderWriter / PECOFFLinkingContext.h
1 //===- lld/ReaderWriter/PECOFFLinkingContext.h ----------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLD_READER_WRITER_PECOFF_LINKING_CONTEXT_H
11 #define LLD_READER_WRITER_PECOFF_LINKING_CONTEXT_H
12
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"
21 #include <map>
22 #include <mutex>
23 #include <set>
24 #include <vector>
25
26 using llvm::COFF::MachineTypes;
27 using llvm::COFF::WindowsSubsystem;
28
29 static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};
30
31 namespace lld {
32
33 class PECOFFLinkingContext : public LinkingContext {
34 public:
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);
53   }
54
55   struct Version {
56     Version(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
57     int majorVersion;
58     int minorVersion;
59   };
60
61   struct ExportDesc {
62     ExportDesc()
63         : ordinal(-1), noname(false), isData(false), isPrivate(false) {}
64
65     bool operator<(const ExportDesc &other) const {
66       return getExternalName().compare(other.getExternalName()) < 0;
67     }
68
69     StringRef getRealName() const {
70       return mangledName.empty() ? name : mangledName;
71     }
72
73     StringRef getExternalName() const {
74       return externalName.empty() ? name : externalName;
75     }
76
77     std::string name;
78     std::string externalName;
79     std::string mangledName;
80     int ordinal;
81     bool noname;
82     bool isData;
83     bool isPrivate;
84   };
85
86   typedef bool (*ParseDirectives)(int, const char **, PECOFFLinkingContext &,
87                                   raw_ostream &);
88
89   /// \brief Casting support
90   static bool classof(const LinkingContext *info) { return true; }
91
92   Writer &writer() const override;
93   bool validateImpl(raw_ostream &diagnostics) override;
94
95   void addPasses(PassManager &pm) override;
96
97   bool createImplicitFiles(
98       std::vector<std::unique_ptr<File> > &result) override;
99
100   bool is64Bit() const {
101     return _machineType == llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
102   }
103
104   // Returns a set of all defined symbols in input files.
105   const std::set<std::string> &definedSymbols();
106
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 {
110     return 0x1000;
111   }
112
113   void appendInputSearchPath(StringRef dirPath) {
114     _inputSearchPaths.push_back(dirPath);
115   }
116
117   const std::vector<StringRef> getInputSearchPaths() {
118     return _inputSearchPaths;
119   }
120
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));
125   }
126
127   StringRef searchLibraryFile(StringRef path) const;
128
129   StringRef decorateSymbol(StringRef name) const;
130   StringRef undecorateSymbol(StringRef name) const;
131
132   void setEntrySymbolName(StringRef name) { _entry = name; }
133   StringRef getEntrySymbolName() const { return _entry; }
134
135   void setHasEntry(bool val) { _hasEntry = val; }
136   bool hasEntry() const { return _hasEntry; }
137
138   void setBaseAddress(uint64_t addr) { _baseAddress = addr; }
139   uint64_t getBaseAddress() const;
140
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; }
145
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; }
150
151   void setSectionDefaultAlignment(uint32_t val) {
152     _sectionDefaultAlignment = val;
153   }
154   uint32_t getSectionDefaultAlignment() const {
155     return _sectionDefaultAlignment;
156   }
157
158   void setSubsystem(WindowsSubsystem ss) { _subsystem = ss; }
159   WindowsSubsystem getSubsystem() const { return _subsystem; }
160
161   void setMachineType(MachineTypes type) { _machineType = type; }
162   MachineTypes getMachineType() const { return _machineType; }
163
164   void setImageVersion(const Version &version) { _imageVersion = version; }
165   Version getImageVersion() const { return _imageVersion; }
166
167   void setMinOSVersion(const Version &version) { _minOSVersion = version; }
168   Version getMinOSVersion() const { return _minOSVersion; }
169
170   void setNxCompat(bool nxCompat) { _nxCompat = nxCompat; }
171   bool isNxCompat() const { return _nxCompat; }
172
173   void setLargeAddressAware(bool val) { _largeAddressAware = val; }
174   bool getLargeAddressAware() const { return _largeAddressAware; }
175
176   void setAllowBind(bool val) { _allowBind = val; }
177   bool getAllowBind() const { return _allowBind; }
178
179   void setAllowIsolation(bool val) { _allowIsolation = val; }
180   bool getAllowIsolation() const { return _allowIsolation; }
181
182   void setSwapRunFromCD(bool val) { _swapRunFromCD = val; }
183   bool getSwapRunFromCD() const { return _swapRunFromCD; }
184
185   void setSwapRunFromNet(bool val) { _swapRunFromNet = val; }
186   bool getSwapRunFromNet() const { return _swapRunFromNet; }
187
188   void setBaseRelocationEnabled(bool val) { _baseRelocationEnabled = val; }
189   bool getBaseRelocationEnabled() const { return _baseRelocationEnabled; }
190
191   void setTerminalServerAware(bool val) { _terminalServerAware = val; }
192   bool isTerminalServerAware() const { return _terminalServerAware; }
193
194   void setDynamicBaseEnabled(bool val) { _dynamicBaseEnabled = val; }
195   bool getDynamicBaseEnabled() const { return _dynamicBaseEnabled; }
196
197   void setCreateManifest(bool val) { _createManifest = val; }
198   bool getCreateManifest() const { return _createManifest; }
199
200   void setManifestOutputPath(std::string val) { _manifestOutputPath = val; }
201   const std::string &getManifestOutputPath() const {
202     return _manifestOutputPath;
203   }
204
205   void setEmbedManifest(bool val) { _embedManifest = val; }
206   bool getEmbedManifest() const { return _embedManifest; }
207
208   void setManifestId(int val) { _manifestId = val; }
209   int getManifestId() const { return _manifestId; }
210
211   void setManifestUAC(bool val) { _manifestUAC = val; }
212   bool getManifestUAC() const { return _manifestUAC; }
213
214   void setManifestLevel(std::string val) { _manifestLevel = std::move(val); }
215   const std::string &getManifestLevel() const { return _manifestLevel; }
216
217   void setManifestUiAccess(std::string val) { _manifestUiAccess = val; }
218   const std::string &getManifestUiAccess() const { return _manifestUiAccess; }
219
220   void setManifestDependency(std::string val) { _manifestDependency = val; }
221   const std::string &getManifestDependency() const {
222     return _manifestDependency;
223   }
224
225   void setIsDll(bool val) { _isDll = val; }
226   bool isDll() const { return _isDll; }
227
228   void setSafeSEH(bool val) {
229     if (val)
230       _requireSEH = true;
231     else
232       _noSEH = true;
233   }
234   bool requireSEH() const { return _requireSEH; }
235   bool noSEH() const { return _noSEH; }
236
237   void setHighEntropyVA(bool val) { _highEntropyVA = val; }
238   bool getHighEntropyVA() const { return _highEntropyVA; }
239
240   void setOutputImportLibraryPath(const std::string &val) { _implib = val; }
241   std::string getOutputImportLibraryPath() const;
242
243   void setDebug(bool val) { _debug = val; }
244   bool getDebug() { return _debug; }
245
246   void setPDBFilePath(StringRef str) { _pdbFilePath = str; }
247   std::string getPDBFilePath() const;
248
249   void addDelayLoadDLL(StringRef dll) {
250     _delayLoadDLLs.insert(dll.lower());
251   }
252   bool isDelayLoadDLL(StringRef dll) const {
253     return _delayLoadDLLs.count(dll.lower()) == 1;
254   }
255
256   StringRef getOutputSectionName(StringRef sectionName) const;
257   bool addSectionRenaming(raw_ostream &diagnostics,
258                           StringRef from, StringRef to);
259
260   const std::set<std::string> &getAlternateNames(StringRef name) {
261     return _alternateNames[name];
262   }
263
264   void addAlternateName(StringRef weak, StringRef def) {
265     _alternateNames[def].insert(weak);
266   }
267
268   void addNoDefaultLib(StringRef path) {
269     if (path.endswith_lower(".lib"))
270       _noDefaultLibs.insert(path.drop_back(4).lower());
271     else
272       _noDefaultLibs.insert(path.lower());
273   }
274
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;
279   }
280
281   void setNoDefaultLibAll(bool val) { _noDefaultLibAll = val; }
282   bool getNoDefaultLibAll() const { return _noDefaultLibAll; }
283
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;
287
288   void setDosStub(ArrayRef<uint8_t> data) { _dosStub = data; }
289   ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
290
291   void addDllExport(ExportDesc &desc);
292   std::vector<ExportDesc> &getDllExports() { return _dllExports; }
293   const std::vector<ExportDesc> &getDllExports() const { return _dllExports; }
294
295   StringRef getDelayLoadHelperName() const {
296     return is64Bit() ? "__delayLoadHelper2" : "___delayLoadHelper2@8";
297   }
298
299   StringRef allocate(StringRef ref) const {
300     _allocMutex.lock();
301     char *x = _allocator.Allocate<char>(ref.size() + 1);
302     _allocMutex.unlock();
303     memcpy(x, ref.data(), ref.size());
304     x[ref.size()] = '\0';
305     return x;
306   }
307
308   ArrayRef<uint8_t> allocate(ArrayRef<uint8_t> array) const {
309     size_t size = array.size();
310     _allocMutex.lock();
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());
315   }
316
317   template <typename T> T &allocateCopy(const T &x) const {
318     _allocMutex.lock();
319     T *r = new (_allocator) T(x);
320     _allocMutex.unlock();
321     return *r;
322   }
323
324   void addLibraryFile(std::unique_ptr<FileNode> file);
325
326   void setModuleDefinitionFile(const std::string val) {
327     _moduleDefinitionFile = val;
328   }
329   std::string getModuleDefinitionFile() const {
330     return _moduleDefinitionFile;
331   }
332
333   std::recursive_mutex &getMutex() { return _mutex; }
334
335   void setParseDirectives(ParseDirectives parseDirectives) {
336     _parseDirectives = parseDirectives;
337   }
338
339   ParseDirectives getParseDirectives() {
340     return _parseDirectives;
341   }
342
343 protected:
344   /// Method to create a internal file for the entry symbol
345   std::unique_ptr<File> createEntrySymbolFile() const override;
346
347   /// Method to create a internal file for an undefined symbol
348   std::unique_ptr<File> createUndefinedSymbolFile() const override;
349
350 private:
351   enum : uint64_t {
352     invalidBaseAddress = UINT64_MAX,
353     pe32DefaultBaseAddress = 0x400000U,
354     pe32PlusDefaultBaseAddress = 0x140000000U
355   };
356
357   std::recursive_mutex _mutex;
358   mutable std::mutex _allocMutex;
359
360   std::string _entry;
361
362   // False if /noentry option is given.
363   bool _hasEntry;
364
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;
368
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;
379   bool _nxCompat;
380   bool _largeAddressAware;
381   bool _allowBind;
382   bool _allowIsolation;
383   bool _swapRunFromCD;
384   bool _swapRunFromNet;
385   bool _baseRelocationEnabled;
386   bool _terminalServerAware;
387   bool _dynamicBaseEnabled;
388   bool _createManifest;
389   std::string _manifestOutputPath;
390   bool _embedManifest;
391   int _manifestId;
392   bool _manifestUAC;
393   std::string _manifestLevel;
394   std::string _manifestUiAccess;
395   std::string _manifestDependency;
396   bool _isDll;
397   bool _highEntropyVA;
398
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.
402   bool _requireSEH;
403
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.
407   bool _noSEH;
408
409   // /IMPLIB command line option.
410   std::string _implib;
411
412   // True if /DEBUG is given.
413   bool _debug;
414
415   // PDB file output path. NB: this is dummy -- LLD just creates the empty file.
416   std::string _pdbFilePath;
417
418   // /DELAYLOAD option.
419   std::set<std::string> _delayLoadDLLs;
420
421   // The set to store /nodefaultlib arguments.
422   std::set<std::string> _noDefaultLibs;
423
424   std::vector<StringRef> _inputSearchPaths;
425   std::unique_ptr<Writer> _writer;
426
427   // A map for weak aliases.
428   std::map<std::string, std::set<std::string>> _alternateNames;
429
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;
434
435   // Section attributes specified by /section option.
436   std::map<std::string, uint32_t> _sectionSetMask;
437   std::map<std::string, uint32_t> _sectionClearMask;
438
439   // DLLExport'ed symbols.
440   std::vector<ExportDesc> _dllExports;
441
442   // List of files that will be removed on destruction.
443   std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;
444
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;
450
451   // Name of the temporary file for lib.exe subcommand. For debugging
452   // only.
453   std::string _moduleDefinitionFile;
454
455   std::set<std::string> _definedSyms;
456   std::set<Node *> _seen;
457
458   ParseDirectives _parseDirectives;
459 };
460
461 } // end namespace lld
462
463 #endif