/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/Driver.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- Driver.cpp ---------------------------------------------------------===// |
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 | | #include "Driver.h" |
10 | | #include "Config.h" |
11 | | #include "DebugTypes.h" |
12 | | #include "ICF.h" |
13 | | #include "InputFiles.h" |
14 | | #include "MarkLive.h" |
15 | | #include "MinGW.h" |
16 | | #include "SymbolTable.h" |
17 | | #include "Symbols.h" |
18 | | #include "Writer.h" |
19 | | #include "lld/Common/Args.h" |
20 | | #include "lld/Common/Driver.h" |
21 | | #include "lld/Common/ErrorHandler.h" |
22 | | #include "lld/Common/Filesystem.h" |
23 | | #include "lld/Common/Memory.h" |
24 | | #include "lld/Common/Threads.h" |
25 | | #include "lld/Common/Timer.h" |
26 | | #include "lld/Common/Version.h" |
27 | | #include "llvm/ADT/Optional.h" |
28 | | #include "llvm/ADT/StringSwitch.h" |
29 | | #include "llvm/BinaryFormat/Magic.h" |
30 | | #include "llvm/Object/ArchiveWriter.h" |
31 | | #include "llvm/Object/COFFImportFile.h" |
32 | | #include "llvm/Object/COFFModuleDefinition.h" |
33 | | #include "llvm/Object/WindowsMachineFlag.h" |
34 | | #include "llvm/Option/Arg.h" |
35 | | #include "llvm/Option/ArgList.h" |
36 | | #include "llvm/Option/Option.h" |
37 | | #include "llvm/Support/Debug.h" |
38 | | #include "llvm/Support/LEB128.h" |
39 | | #include "llvm/Support/Path.h" |
40 | | #include "llvm/Support/Process.h" |
41 | | #include "llvm/Support/TarWriter.h" |
42 | | #include "llvm/Support/TargetSelect.h" |
43 | | #include "llvm/Support/raw_ostream.h" |
44 | | #include "llvm/ToolDrivers/llvm-lib/LibDriver.h" |
45 | | #include <algorithm> |
46 | | #include <future> |
47 | | #include <memory> |
48 | | |
49 | | using namespace llvm; |
50 | | using namespace llvm::object; |
51 | | using namespace llvm::COFF; |
52 | | using llvm::sys::Process; |
53 | | |
54 | | namespace lld { |
55 | | namespace coff { |
56 | | |
57 | | static Timer inputFileTimer("Input File Reading", Timer::root()); |
58 | | |
59 | | Configuration *config; |
60 | | LinkerDriver *driver; |
61 | | |
62 | 689 | bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &diag) { |
63 | 689 | errorHandler().logName = args::getFilenameWithoutExe(args[0]); |
64 | 689 | errorHandler().errorOS = &diag; |
65 | 689 | errorHandler().colorDiagnostics = diag.has_colors(); |
66 | 689 | errorHandler().errorLimitExceededMsg = |
67 | 689 | "too many errors emitted, stopping now" |
68 | 689 | " (use /errorlimit:0 to see all errors)"; |
69 | 689 | errorHandler().exitEarly = canExitEarly; |
70 | 689 | config = make<Configuration>(); |
71 | 689 | |
72 | 689 | symtab = make<SymbolTable>(); |
73 | 689 | |
74 | 689 | driver = make<LinkerDriver>(); |
75 | 689 | driver->link(args); |
76 | 689 | |
77 | 689 | // Call exit() if we can to avoid calling destructors. |
78 | 689 | if (canExitEarly) |
79 | 0 | exitLld(errorCount() ? 1 : 0); |
80 | 689 | |
81 | 689 | freeArena(); |
82 | 689 | ObjFile::instances.clear(); |
83 | 689 | ImportFile::instances.clear(); |
84 | 689 | BitcodeFile::instances.clear(); |
85 | 689 | memset(MergeChunk::instances, 0, sizeof(MergeChunk::instances)); |
86 | 689 | return !errorCount(); |
87 | 689 | } |
88 | | |
89 | | // Parse options of the form "old;new". |
90 | | static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args, |
91 | 1.36k | unsigned id) { |
92 | 1.36k | auto *arg = args.getLastArg(id); |
93 | 1.36k | if (!arg) |
94 | 1.35k | return {"", ""}; |
95 | 5 | |
96 | 5 | StringRef s = arg->getValue(); |
97 | 5 | std::pair<StringRef, StringRef> ret = s.split(';'); |
98 | 5 | if (ret.second.empty()) |
99 | 2 | error(arg->getSpelling() + " expects 'old;new' format, but got " + s); |
100 | 5 | return ret; |
101 | 5 | } |
102 | | |
103 | | // Drop directory components and replace extension with ".exe" or ".dll". |
104 | 35 | static std::string getOutputPath(StringRef path) { |
105 | 35 | auto p = path.find_last_of("\\/"); |
106 | 35 | StringRef s = (p == StringRef::npos) ? path3 : path.substr(p + 1)32 ; |
107 | 35 | const char* e = config->dll ? ".dll"14 : ".exe"21 ; |
108 | 35 | return (s.substr(0, s.rfind('.')) + e).str(); |
109 | 35 | } |
110 | | |
111 | | // Returns true if S matches /crtend.?\.o$/. |
112 | 66 | static bool isCrtend(StringRef s) { |
113 | 66 | if (!s.endswith(".o")) |
114 | 38 | return false; |
115 | 28 | s = s.drop_back(2); |
116 | 28 | if (s.endswith("crtend")) |
117 | 2 | return true; |
118 | 26 | return !s.empty() && s.drop_back().endswith("crtend"); |
119 | 26 | } |
120 | | |
121 | | // ErrorOr is not default constructible, so it cannot be used as the type |
122 | | // parameter of a future. |
123 | | // FIXME: We could open the file in createFutureForFile and avoid needing to |
124 | | // return an error here, but for the moment that would cost us a file descriptor |
125 | | // (a limited resource on Windows) for the duration that the future is pending. |
126 | | using MBErrPair = std::pair<std::unique_ptr<MemoryBuffer>, std::error_code>; |
127 | | |
128 | | // Create a std::future that opens and maps a file using the best strategy for |
129 | | // the host platform. |
130 | 977 | static std::future<MBErrPair> createFutureForFile(std::string path) { |
131 | | #if _WIN32 |
132 | | // On Windows, file I/O is relatively slow so it is best to do this |
133 | | // asynchronously. |
134 | | auto strategy = std::launch::async; |
135 | | #else |
136 | | auto strategy = std::launch::deferred; |
137 | 977 | #endif |
138 | 977 | return std::async(strategy, [=]() { |
139 | 977 | auto mbOrErr = MemoryBuffer::getFile(path, |
140 | 977 | /*FileSize*/ -1, |
141 | 977 | /*RequiresNullTerminator*/ false); |
142 | 977 | if (!mbOrErr) |
143 | 70 | return MBErrPair{nullptr, mbOrErr.getError()}; |
144 | 907 | return MBErrPair{std::move(*mbOrErr), std::error_code()}; |
145 | 907 | }); |
146 | 977 | } |
147 | | |
148 | | // Symbol names are mangled by prepending "_" on x86. |
149 | 7.43k | static StringRef mangle(StringRef sym) { |
150 | 7.43k | assert(config->machine != IMAGE_FILE_MACHINE_UNKNOWN); |
151 | 7.43k | if (config->machine == I386) |
152 | 1.24k | return saver.save("_" + sym); |
153 | 6.18k | return sym; |
154 | 6.18k | } |
155 | | |
156 | 1.14k | static bool findUnderscoreMangle(StringRef sym) { |
157 | 1.14k | Symbol *s = symtab->findMangle(mangle(sym)); |
158 | 1.14k | return s && !isa<Undefined>(s)288 ; |
159 | 1.14k | } |
160 | | |
161 | 908 | MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> mb) { |
162 | 908 | MemoryBufferRef mbref = *mb; |
163 | 908 | make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take ownership |
164 | 908 | |
165 | 908 | if (driver->tar) |
166 | 7 | driver->tar->append(relativeToRoot(mbref.getBufferIdentifier()), |
167 | 7 | mbref.getBuffer()); |
168 | 908 | return mbref; |
169 | 908 | } |
170 | | |
171 | | void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb, |
172 | 907 | bool wholeArchive) { |
173 | 907 | StringRef filename = mb->getBufferIdentifier(); |
174 | 907 | |
175 | 907 | MemoryBufferRef mbref = takeBuffer(std::move(mb)); |
176 | 907 | filePaths.push_back(filename); |
177 | 907 | |
178 | 907 | // File type is detected by contents, not by file extension. |
179 | 907 | switch (identify_magic(mbref.getBuffer())) { |
180 | 907 | case file_magic::windows_resource: |
181 | 13 | resources.push_back(mbref); |
182 | 13 | break; |
183 | 907 | case file_magic::archive: |
184 | 102 | if (wholeArchive) { |
185 | 5 | std::unique_ptr<Archive> file = |
186 | 5 | CHECK(Archive::create(mbref), filename + ": failed to parse archive"); |
187 | 5 | |
188 | 5 | for (MemoryBufferRef m : getArchiveMembers(file.get())) |
189 | 5 | addArchiveBuffer(m, "<whole-archive>", filename, 0); |
190 | 5 | return; |
191 | 5 | } |
192 | 97 | symtab->addFile(make<ArchiveFile>(mbref)); |
193 | 97 | break; |
194 | 97 | case file_magic::bitcode: |
195 | 65 | symtab->addFile(make<BitcodeFile>(mbref, "", 0)); |
196 | 65 | break; |
197 | 719 | case file_magic::coff_object: |
198 | 719 | case file_magic::coff_import_library: |
199 | 719 | symtab->addFile(make<ObjFile>(mbref)); |
200 | 719 | break; |
201 | 719 | case file_magic::pdb: |
202 | 6 | loadTypeServerSource(mbref); |
203 | 6 | break; |
204 | 719 | case file_magic::coff_cl_gl_object: |
205 | 1 | error(filename + ": is not a native COFF file. Recompile without /GL"); |
206 | 1 | break; |
207 | 719 | case file_magic::pecoff_executable: |
208 | 1 | if (filename.endswith_lower(".dll")) { |
209 | 1 | error(filename + ": bad file type. Did you specify a DLL instead of an " |
210 | 1 | "import library?"); |
211 | 1 | break; |
212 | 1 | } |
213 | 0 | LLVM_FALLTHROUGH; |
214 | 0 | default: |
215 | 0 | error(mbref.getBufferIdentifier() + ": unknown file type"); |
216 | 0 | break; |
217 | 907 | } |
218 | 907 | } |
219 | | |
220 | 976 | void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive) { |
221 | 976 | auto future = |
222 | 976 | std::make_shared<std::future<MBErrPair>>(createFutureForFile(path)); |
223 | 976 | std::string pathStr = path; |
224 | 976 | enqueueTask([=]() { |
225 | 976 | auto mbOrErr = future->get(); |
226 | 976 | if (mbOrErr.second) { |
227 | 70 | std::string msg = |
228 | 70 | "could not open '" + pathStr + "': " + mbOrErr.second.message(); |
229 | 70 | // Check if the filename is a typo for an option flag. OptTable thinks |
230 | 70 | // that all args that are not known options and that start with / are |
231 | 70 | // filenames, but e.g. `/nodefaultlibs` is more likely a typo for |
232 | 70 | // the option `/nodefaultlib` than a reference to a file in the root |
233 | 70 | // directory. |
234 | 70 | std::string nearest; |
235 | 70 | if (COFFOptTable().findNearest(pathStr, nearest) > 1) |
236 | 68 | error(msg); |
237 | 2 | else |
238 | 2 | error(msg + "; did you mean '" + nearest + "'"); |
239 | 70 | } else |
240 | 906 | driver->addBuffer(std::move(mbOrErr.first), wholeArchive); |
241 | 976 | }); |
242 | 976 | } |
243 | | |
244 | | void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, |
245 | | StringRef parentName, |
246 | 161 | uint64_t offsetInArchive) { |
247 | 161 | file_magic magic = identify_magic(mb.getBuffer()); |
248 | 161 | if (magic == file_magic::coff_import_library) { |
249 | 109 | InputFile *imp = make<ImportFile>(mb); |
250 | 109 | imp->parentName = parentName; |
251 | 109 | symtab->addFile(imp); |
252 | 109 | return; |
253 | 109 | } |
254 | 52 | |
255 | 52 | InputFile *obj; |
256 | 52 | if (magic == file_magic::coff_object) { |
257 | 40 | obj = make<ObjFile>(mb); |
258 | 40 | } else if (12 magic == file_magic::bitcode12 ) { |
259 | 12 | obj = make<BitcodeFile>(mb, parentName, offsetInArchive); |
260 | 12 | } else { |
261 | 0 | error("unknown file type: " + mb.getBufferIdentifier()); |
262 | 0 | return; |
263 | 0 | } |
264 | 52 | |
265 | 52 | obj->parentName = parentName; |
266 | 52 | symtab->addFile(obj); |
267 | 52 | log("Loaded " + toString(obj) + " for " + symName); |
268 | 52 | } |
269 | | |
270 | | void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, |
271 | | const Archive::Symbol &sym, |
272 | 156 | StringRef parentName) { |
273 | 156 | |
274 | 156 | auto reportBufferError = [=](Error &&e, StringRef childName) { |
275 | 0 | fatal("could not get the buffer for the member defining symbol " + |
276 | 0 | toCOFFString(sym) + ": " + parentName + "(" + childName + "): " + |
277 | 0 | toString(std::move(e))); |
278 | 0 | }; |
279 | 156 | |
280 | 156 | if (!c.getParent()->isThin()) { |
281 | 155 | uint64_t offsetInArchive = c.getChildOffset(); |
282 | 155 | Expected<MemoryBufferRef> mbOrErr = c.getMemoryBufferRef(); |
283 | 155 | if (!mbOrErr) |
284 | 0 | reportBufferError(mbOrErr.takeError(), check(c.getFullName())); |
285 | 155 | MemoryBufferRef mb = mbOrErr.get(); |
286 | 155 | enqueueTask([=]() { |
287 | 155 | driver->addArchiveBuffer(mb, toCOFFString(sym), parentName, |
288 | 155 | offsetInArchive); |
289 | 155 | }); |
290 | 155 | return; |
291 | 155 | } |
292 | 1 | |
293 | 1 | std::string childName = CHECK( |
294 | 1 | c.getFullName(), |
295 | 1 | "could not get the filename for the member defining symbol " + |
296 | 1 | toCOFFString(sym)); |
297 | 1 | auto future = std::make_shared<std::future<MBErrPair>>( |
298 | 1 | createFutureForFile(childName)); |
299 | 1 | enqueueTask([=]() { |
300 | 1 | auto mbOrErr = future->get(); |
301 | 1 | if (mbOrErr.second) |
302 | 0 | reportBufferError(errorCodeToError(mbOrErr.second), childName); |
303 | 1 | driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), |
304 | 1 | toCOFFString(sym), parentName, |
305 | 1 | /*OffsetInArchive=*/0); |
306 | 1 | }); |
307 | 1 | } |
308 | | |
309 | 27 | static bool isDecorated(StringRef sym) { |
310 | 27 | return sym.startswith("@") || sym.contains("@@") || sym.startswith("?") || |
311 | 27 | (!config->mingw && sym.contains('@')25 ); |
312 | 27 | } |
313 | | |
314 | | // Parses .drectve section contents and returns a list of files |
315 | | // specified by /defaultlib. |
316 | 1.04k | void LinkerDriver::parseDirectives(InputFile *file) { |
317 | 1.04k | StringRef s = file->getDirectives(); |
318 | 1.04k | if (s.empty()) |
319 | 847 | return; |
320 | 201 | |
321 | 201 | log("Directives: " + toString(file) + ": " + s); |
322 | 201 | |
323 | 201 | ArgParser parser; |
324 | 201 | // .drectve is always tokenized using Windows shell rules. |
325 | 201 | // /EXPORT: option can appear too many times, processing in fastpath. |
326 | 201 | opt::InputArgList args; |
327 | 201 | std::vector<StringRef> exports; |
328 | 201 | std::tie(args, exports) = parser.parseDirectives(s); |
329 | 201 | |
330 | 201 | for (StringRef e : exports) { |
331 | 116 | // If a common header file contains dllexported function |
332 | 116 | // declarations, many object files may end up with having the |
333 | 116 | // same /EXPORT options. In order to save cost of parsing them, |
334 | 116 | // we dedup them first. |
335 | 116 | if (!directivesExports.insert(e).second) |
336 | 0 | continue; |
337 | 116 | |
338 | 116 | Export exp = parseExport(e); |
339 | 116 | if (config->machine == I386 && config->mingw19 ) { |
340 | 2 | if (!isDecorated(exp.name)) |
341 | 2 | exp.name = saver.save("_" + exp.name); |
342 | 2 | if (!exp.extName.empty() && !isDecorated(exp.extName)0 ) |
343 | 0 | exp.extName = saver.save("_" + exp.extName); |
344 | 2 | } |
345 | 116 | exp.directives = true; |
346 | 116 | config->exports.push_back(exp); |
347 | 116 | } |
348 | 201 | |
349 | 225 | for (auto *arg : args) { |
350 | 225 | switch (arg->getOption().getID()) { |
351 | 225 | case OPT_aligncomm: |
352 | 2 | parseAligncomm(arg->getValue()); |
353 | 2 | break; |
354 | 225 | case OPT_alternatename: |
355 | 3 | parseAlternateName(arg->getValue()); |
356 | 3 | break; |
357 | 225 | case OPT_defaultlib: |
358 | 191 | if (Optional<StringRef> path = findLib(arg->getValue())) |
359 | 1 | enqueuePath(*path, false); |
360 | 191 | break; |
361 | 225 | case OPT_entry: |
362 | 1 | config->entry = addUndefined(mangle(arg->getValue())); |
363 | 1 | break; |
364 | 225 | case OPT_failifmismatch: |
365 | 0 | checkFailIfMismatch(arg->getValue(), file); |
366 | 0 | break; |
367 | 225 | case OPT_incl: |
368 | 27 | addUndefined(arg->getValue()); |
369 | 27 | break; |
370 | 225 | case OPT_merge: |
371 | 0 | parseMerge(arg->getValue()); |
372 | 0 | break; |
373 | 225 | case OPT_nodefaultlib: |
374 | 0 | config->noDefaultLibs.insert(doFindLib(arg->getValue()).lower()); |
375 | 0 | break; |
376 | 225 | case OPT_section: |
377 | 0 | parseSection(arg->getValue()); |
378 | 0 | break; |
379 | 225 | case OPT_subsystem: |
380 | 1 | parseSubsystem(arg->getValue(), &config->subsystem, |
381 | 1 | &config->majorOSVersion, &config->minorOSVersion); |
382 | 1 | break; |
383 | 225 | // Only add flags here that link.exe accepts in |
384 | 225 | // `#pragma comment(linker, "/flag")`-generated sections. |
385 | 225 | case OPT_editandcontinue: |
386 | 0 | case OPT_guardsym: |
387 | 0 | case OPT_throwingnew: |
388 | 0 | break; |
389 | 0 | default: |
390 | 0 | error(arg->getSpelling() + " is not allowed in .drectve"); |
391 | 225 | } |
392 | 225 | } |
393 | 201 | } |
394 | | |
395 | | // Find file from search paths. You can omit ".obj", this function takes |
396 | | // care of that. Note that the returned path is not guaranteed to exist. |
397 | 988 | StringRef LinkerDriver::doFindFile(StringRef filename) { |
398 | 988 | bool hasPathSep = (filename.find_first_of("/\\") != StringRef::npos); |
399 | 988 | if (hasPathSep) |
400 | 875 | return filename; |
401 | 113 | bool hasExt = filename.contains('.'); |
402 | 132 | for (StringRef dir : searchPaths) { |
403 | 132 | SmallString<128> path = dir; |
404 | 132 | sys::path::append(path, filename); |
405 | 132 | if (sys::fs::exists(path.str())) |
406 | 46 | return saver.save(path.str()); |
407 | 86 | if (!hasExt) { |
408 | 58 | path.append(".obj"); |
409 | 58 | if (sys::fs::exists(path.str())) |
410 | 0 | return saver.save(path.str()); |
411 | 58 | } |
412 | 86 | } |
413 | 113 | return filename67 ; |
414 | 113 | } |
415 | | |
416 | 1.93k | static Optional<sys::fs::UniqueID> getUniqueID(StringRef path) { |
417 | 1.93k | sys::fs::UniqueID ret; |
418 | 1.93k | if (sys::fs::getUniqueID(path, ret)) |
419 | 138 | return None; |
420 | 1.80k | return ret; |
421 | 1.80k | } |
422 | | |
423 | | // Resolves a file path. This never returns the same path |
424 | | // (in that case, it returns None). |
425 | 966 | Optional<StringRef> LinkerDriver::findFile(StringRef filename) { |
426 | 966 | StringRef path = doFindFile(filename); |
427 | 966 | |
428 | 966 | if (Optional<sys::fs::UniqueID> id = getUniqueID(path)) { |
429 | 898 | bool seen = !visitedFiles.insert(*id).second; |
430 | 898 | if (seen) |
431 | 4 | return None; |
432 | 962 | } |
433 | 962 | |
434 | 962 | if (path.endswith_lower(".lib")) |
435 | 87 | visitedLibs.insert(sys::path::filename(path)); |
436 | 962 | return path; |
437 | 962 | } |
438 | | |
439 | | // MinGW specific. If an embedded directive specified to link to |
440 | | // foo.lib, but it isn't found, try libfoo.a instead. |
441 | 1 | StringRef LinkerDriver::doFindLibMinGW(StringRef filename) { |
442 | 1 | if (filename.contains('/') || filename.contains('\\')) |
443 | 0 | return filename; |
444 | 1 | |
445 | 1 | SmallString<128> s = filename; |
446 | 1 | sys::path::replace_extension(s, ".a"); |
447 | 1 | StringRef libName = saver.save("lib" + s.str()); |
448 | 1 | return doFindFile(libName); |
449 | 1 | } |
450 | | |
451 | | // Find library file from search path. |
452 | 16 | StringRef LinkerDriver::doFindLib(StringRef filename) { |
453 | 16 | // Add ".lib" to Filename if that has no file extension. |
454 | 16 | bool hasExt = filename.contains('.'); |
455 | 16 | if (!hasExt) |
456 | 7 | filename = saver.save(filename + ".lib"); |
457 | 16 | StringRef ret = doFindFile(filename); |
458 | 16 | // For MinGW, if the find above didn't turn up anything, try |
459 | 16 | // looking for a MinGW formatted library name. |
460 | 16 | if (config->mingw && ret == filename1 ) |
461 | 1 | return doFindLibMinGW(filename); |
462 | 15 | return ret; |
463 | 15 | } |
464 | | |
465 | | // Resolves a library path. /nodefaultlib options are taken into |
466 | | // consideration. This never returns the same path (in that case, |
467 | | // it returns None). |
468 | 200 | Optional<StringRef> LinkerDriver::findLib(StringRef filename) { |
469 | 200 | if (config->noDefaultLibAll) |
470 | 184 | return None; |
471 | 16 | if (!visitedLibs.insert(filename.lower()).second) |
472 | 4 | return None; |
473 | 12 | |
474 | 12 | StringRef path = doFindLib(filename); |
475 | 12 | if (config->noDefaultLibs.count(path.lower())) |
476 | 4 | return None; |
477 | 8 | |
478 | 8 | if (Optional<sys::fs::UniqueID> id = getUniqueID(path)) |
479 | 6 | if (!visitedFiles.insert(*id).second) |
480 | 0 | return None; |
481 | 8 | return path; |
482 | 8 | } |
483 | | |
484 | | // Parses LIB environment which contains a list of search paths. |
485 | 681 | void LinkerDriver::addLibSearchPaths() { |
486 | 681 | Optional<std::string> envOpt = Process::GetEnv("LIB"); |
487 | 681 | if (!envOpt.hasValue()) |
488 | 677 | return; |
489 | 4 | StringRef env = saver.save(*envOpt); |
490 | 8 | while (!env.empty()) { |
491 | 4 | StringRef path; |
492 | 4 | std::tie(path, env) = env.split(';'); |
493 | 4 | searchPaths.push_back(path); |
494 | 4 | } |
495 | 4 | } |
496 | | |
497 | 862 | Symbol *LinkerDriver::addUndefined(StringRef name) { |
498 | 862 | Symbol *b = symtab->addUndefined(name); |
499 | 862 | if (!b->isGCRoot) { |
500 | 836 | b->isGCRoot = true; |
501 | 836 | config->gcroot.push_back(b); |
502 | 836 | } |
503 | 862 | return b; |
504 | 862 | } |
505 | | |
506 | 662 | StringRef LinkerDriver::mangleMaybe(Symbol *s) { |
507 | 662 | // If the plain symbol name has already been resolved, do nothing. |
508 | 662 | Undefined *unmangled = dyn_cast<Undefined>(s); |
509 | 662 | if (!unmangled) |
510 | 596 | return ""; |
511 | 66 | |
512 | 66 | // Otherwise, see if a similar, mangled symbol exists in the symbol table. |
513 | 66 | Symbol *mangled = symtab->findMangle(unmangled->getName()); |
514 | 66 | if (!mangled) |
515 | 43 | return ""; |
516 | 23 | |
517 | 23 | // If we find a similar mangled symbol, make this an alias to it and return |
518 | 23 | // its name. |
519 | 23 | log(unmangled->getName() + " aliased to " + mangled->getName()); |
520 | 23 | unmangled->weakAlias = symtab->addUndefined(mangled->getName()); |
521 | 23 | return mangled->getName(); |
522 | 23 | } |
523 | | |
524 | | // Windows specific -- find default entry point name. |
525 | | // |
526 | | // There are four different entry point functions for Windows executables, |
527 | | // each of which corresponds to a user-defined "main" function. This function |
528 | | // infers an entry point from a user-defined "main" function. |
529 | 57 | StringRef LinkerDriver::findDefaultEntry() { |
530 | 57 | assert(config->subsystem != IMAGE_SUBSYSTEM_UNKNOWN && |
531 | 57 | "must handle /subsystem before calling this"); |
532 | 57 | |
533 | 57 | if (config->mingw) |
534 | 7 | return mangle(config->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI |
535 | 7 | ? "WinMainCRTStartup"1 |
536 | 7 | : "mainCRTStartup"6 ); |
537 | 50 | |
538 | 50 | if (config->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { |
539 | 14 | if (findUnderscoreMangle("wWinMain")) { |
540 | 6 | if (!findUnderscoreMangle("WinMain")) |
541 | 5 | return mangle("wWinMainCRTStartup"); |
542 | 1 | warn("found both wWinMain and WinMain; using latter"); |
543 | 1 | } |
544 | 14 | return mangle("WinMainCRTStartup")9 ; |
545 | 36 | } |
546 | 36 | if (findUnderscoreMangle("wmain")) { |
547 | 6 | if (!findUnderscoreMangle("main")) |
548 | 5 | return mangle("wmainCRTStartup"); |
549 | 1 | warn("found both wmain and main; using latter"); |
550 | 1 | } |
551 | 36 | return mangle("mainCRTStartup")31 ; |
552 | 36 | } |
553 | | |
554 | 459 | WindowsSubsystem LinkerDriver::inferSubsystem() { |
555 | 459 | if (config->dll) |
556 | 166 | return IMAGE_SUBSYSTEM_WINDOWS_GUI; |
557 | 293 | if (config->mingw) |
558 | 22 | return IMAGE_SUBSYSTEM_WINDOWS_CUI; |
559 | 271 | // Note that link.exe infers the subsystem from the presence of these |
560 | 271 | // functions even if /entry: or /nodefaultlib are passed which causes them |
561 | 271 | // to not be called. |
562 | 271 | bool haveMain = findUnderscoreMangle("main"); |
563 | 271 | bool haveWMain = findUnderscoreMangle("wmain"); |
564 | 271 | bool haveWinMain = findUnderscoreMangle("WinMain"); |
565 | 271 | bool haveWWinMain = findUnderscoreMangle("wWinMain"); |
566 | 271 | if (haveMain || haveWMain16 ) { |
567 | 259 | if (haveWinMain || haveWWinMain258 ) { |
568 | 1 | warn(std::string("found ") + (haveMain ? "main" : "wmain"0 ) + " and " + |
569 | 1 | (haveWinMain ? "WinMain" : "wWinMain"0 ) + |
570 | 1 | "; defaulting to /subsystem:console"); |
571 | 1 | } |
572 | 259 | return IMAGE_SUBSYSTEM_WINDOWS_CUI; |
573 | 259 | } |
574 | 12 | if (haveWinMain || haveWWinMain4 ) |
575 | 12 | return IMAGE_SUBSYSTEM_WINDOWS_GUI; |
576 | 0 | return IMAGE_SUBSYSTEM_UNKNOWN; |
577 | 0 | } |
578 | | |
579 | 616 | static uint64_t getDefaultImageBase() { |
580 | 616 | if (config->is64()) |
581 | 496 | return config->dll ? 0x180000000135 : 0x140000000361 ; |
582 | 120 | return config->dll ? 0x1000000036 : 0x40000084 ; |
583 | 120 | } |
584 | | |
585 | | static std::string createResponseFile(const opt::InputArgList &args, |
586 | | ArrayRef<StringRef> filePaths, |
587 | 4 | ArrayRef<StringRef> searchPaths) { |
588 | 4 | SmallString<0> data; |
589 | 4 | raw_svector_ostream os(data); |
590 | 4 | |
591 | 25 | for (auto *arg : args) { |
592 | 25 | switch (arg->getOption().getID()) { |
593 | 25 | case OPT_linkrepro: |
594 | 12 | case OPT_INPUT: |
595 | 12 | case OPT_defaultlib: |
596 | 12 | case OPT_libpath: |
597 | 12 | case OPT_manifest: |
598 | 12 | case OPT_manifest_colon: |
599 | 12 | case OPT_manifestdependency: |
600 | 12 | case OPT_manifestfile: |
601 | 12 | case OPT_manifestinput: |
602 | 12 | case OPT_manifestuac: |
603 | 12 | break; |
604 | 12 | case OPT_implib: |
605 | 4 | case OPT_pdb: |
606 | 4 | case OPT_out: |
607 | 4 | os << arg->getSpelling() << sys::path::filename(arg->getValue()) << "\n"; |
608 | 4 | break; |
609 | 9 | default: |
610 | 9 | os << toString(*arg) << "\n"; |
611 | 25 | } |
612 | 25 | } |
613 | 4 | |
614 | 4 | for (StringRef path : searchPaths) { |
615 | 2 | std::string relPath = relativeToRoot(path); |
616 | 2 | os << "/libpath:" << quote(relPath) << "\n"; |
617 | 2 | } |
618 | 4 | |
619 | 4 | for (StringRef path : filePaths) |
620 | 7 | os << quote(relativeToRoot(path)) << "\n"; |
621 | 4 | |
622 | 4 | return data.str(); |
623 | 4 | } |
624 | | |
625 | | enum class DebugKind { Unknown, None, Full, FastLink, GHash, Dwarf, Symtab }; |
626 | | |
627 | 681 | static DebugKind parseDebugKind(const opt::InputArgList &args) { |
628 | 681 | auto *a = args.getLastArg(OPT_debug, OPT_debug_opt); |
629 | 681 | if (!a) |
630 | 556 | return DebugKind::None; |
631 | 125 | if (a->getNumValues() == 0) |
632 | 106 | return DebugKind::Full; |
633 | 19 | |
634 | 19 | DebugKind debug = StringSwitch<DebugKind>(a->getValue()) |
635 | 19 | .CaseLower("none", DebugKind::None) |
636 | 19 | .CaseLower("full", DebugKind::Full) |
637 | 19 | .CaseLower("fastlink", DebugKind::FastLink) |
638 | 19 | // LLD extensions |
639 | 19 | .CaseLower("ghash", DebugKind::GHash) |
640 | 19 | .CaseLower("dwarf", DebugKind::Dwarf) |
641 | 19 | .CaseLower("symtab", DebugKind::Symtab) |
642 | 19 | .Default(DebugKind::Unknown); |
643 | 19 | |
644 | 19 | if (debug == DebugKind::FastLink) { |
645 | 1 | warn("/debug:fastlink unsupported; using /debug:full"); |
646 | 1 | return DebugKind::Full; |
647 | 1 | } |
648 | 18 | if (debug == DebugKind::Unknown) { |
649 | 1 | error("/debug: unknown option: " + Twine(a->getValue())); |
650 | 1 | return DebugKind::None; |
651 | 1 | } |
652 | 17 | return debug; |
653 | 17 | } |
654 | | |
655 | 681 | static unsigned parseDebugTypes(const opt::InputArgList &args) { |
656 | 681 | unsigned debugTypes = static_cast<unsigned>(DebugType::None); |
657 | 681 | |
658 | 681 | if (auto *a = args.getLastArg(OPT_debugtype)) { |
659 | 3 | SmallVector<StringRef, 3> types; |
660 | 3 | StringRef(a->getValue()) |
661 | 3 | .split(types, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false); |
662 | 3 | |
663 | 4 | for (StringRef type : types) { |
664 | 4 | unsigned v = StringSwitch<unsigned>(type.lower()) |
665 | 4 | .Case("cv", static_cast<unsigned>(DebugType::CV)) |
666 | 4 | .Case("pdata", static_cast<unsigned>(DebugType::PData)) |
667 | 4 | .Case("fixup", static_cast<unsigned>(DebugType::Fixup)) |
668 | 4 | .Default(0); |
669 | 4 | if (v == 0) { |
670 | 3 | warn("/debugtype: unknown option '" + type + "'"); |
671 | 3 | continue; |
672 | 3 | } |
673 | 1 | debugTypes |= v; |
674 | 1 | } |
675 | 3 | return debugTypes; |
676 | 3 | } |
677 | 678 | |
678 | 678 | // Default debug types |
679 | 678 | debugTypes = static_cast<unsigned>(DebugType::CV); |
680 | 678 | if (args.hasArg(OPT_driver)) |
681 | 0 | debugTypes |= static_cast<unsigned>(DebugType::PData); |
682 | 678 | if (args.hasArg(OPT_profile)) |
683 | 7 | debugTypes |= static_cast<unsigned>(DebugType::Fixup); |
684 | 678 | |
685 | 678 | return debugTypes; |
686 | 678 | } |
687 | | |
688 | 681 | static std::string getMapFile(const opt::InputArgList &args) { |
689 | 681 | auto *arg = args.getLastArg(OPT_lldmap, OPT_lldmap_file); |
690 | 681 | if (!arg) |
691 | 667 | return ""; |
692 | 14 | if (arg->getOption().getID() == OPT_lldmap_file) |
693 | 13 | return arg->getValue(); |
694 | 1 | |
695 | 1 | assert(arg->getOption().getID() == OPT_lldmap); |
696 | 1 | StringRef outFile = config->outputFile; |
697 | 1 | return (outFile.substr(0, outFile.rfind('.')) + ".map").str(); |
698 | 1 | } |
699 | | |
700 | 184 | static std::string getImplibPath() { |
701 | 184 | if (!config->implib.empty()) |
702 | 30 | return config->implib; |
703 | 154 | SmallString<128> out = StringRef(config->outputFile); |
704 | 154 | sys::path::replace_extension(out, ".lib"); |
705 | 154 | return out.str(); |
706 | 154 | } |
707 | | |
708 | | // |
709 | | // The import name is caculated as the following: |
710 | | // |
711 | | // | LIBRARY w/ ext | LIBRARY w/o ext | no LIBRARY |
712 | | // -----+----------------+---------------------+------------------ |
713 | | // LINK | {value} | {value}.{.dll/.exe} | {output name} |
714 | | // LIB | {value} | {value}.dll | {output name}.dll |
715 | | // |
716 | 184 | static std::string getImportName(bool asLib) { |
717 | 184 | SmallString<128> out; |
718 | 184 | |
719 | 184 | if (config->importName.empty()) { |
720 | 170 | out.assign(sys::path::filename(config->outputFile)); |
721 | 170 | if (asLib) |
722 | 2 | sys::path::replace_extension(out, ".dll"); |
723 | 170 | } else { |
724 | 14 | out.assign(config->importName); |
725 | 14 | if (!sys::path::has_extension(out)) |
726 | 11 | sys::path::replace_extension(out, |
727 | 11 | (config->dll || asLib4 ) ? ".dll"10 : ".exe"1 ); |
728 | 14 | } |
729 | 184 | |
730 | 184 | return out.str(); |
731 | 184 | } |
732 | | |
733 | 184 | static void createImportLibrary(bool asLib) { |
734 | 184 | std::vector<COFFShortExport> exports; |
735 | 219 | for (Export &e1 : config->exports) { |
736 | 219 | COFFShortExport e2; |
737 | 219 | e2.Name = e1.name; |
738 | 219 | e2.SymbolName = e1.symbolName; |
739 | 219 | e2.ExtName = e1.extName; |
740 | 219 | e2.Ordinal = e1.ordinal; |
741 | 219 | e2.Noname = e1.noname; |
742 | 219 | e2.Data = e1.data; |
743 | 219 | e2.Private = e1.isPrivate; |
744 | 219 | e2.Constant = e1.constant; |
745 | 219 | exports.push_back(e2); |
746 | 219 | } |
747 | 184 | |
748 | 184 | auto handleError = [](Error &&e) { |
749 | 175 | handleAllErrors(std::move(e), |
750 | 175 | [](ErrorInfoBase &eib) { error(eib.message()); }0 ); |
751 | 175 | }; |
752 | 184 | std::string libName = getImportName(asLib); |
753 | 184 | std::string path = getImplibPath(); |
754 | 184 | |
755 | 184 | if (!config->incremental) { |
756 | 159 | handleError(writeImportLibrary(libName, path, exports, config->machine, |
757 | 159 | config->mingw)); |
758 | 159 | return; |
759 | 159 | } |
760 | 25 | |
761 | 25 | // If the import library already exists, replace it only if the contents |
762 | 25 | // have changed. |
763 | 25 | ErrorOr<std::unique_ptr<MemoryBuffer>> oldBuf = MemoryBuffer::getFile( |
764 | 25 | path, /*FileSize*/ -1, /*RequiresNullTerminator*/ false); |
765 | 25 | if (!oldBuf) { |
766 | 14 | handleError(writeImportLibrary(libName, path, exports, config->machine, |
767 | 14 | config->mingw)); |
768 | 14 | return; |
769 | 14 | } |
770 | 11 | |
771 | 11 | SmallString<128> tmpName; |
772 | 11 | if (std::error_code ec = |
773 | 0 | sys::fs::createUniqueFile(path + ".tmp-%%%%%%%%.lib", tmpName)) |
774 | 0 | fatal("cannot create temporary file for import library " + path + ": " + |
775 | 0 | ec.message()); |
776 | 11 | |
777 | 11 | if (Error e = writeImportLibrary(libName, tmpName, exports, config->machine, |
778 | 0 | config->mingw)) { |
779 | 0 | handleError(std::move(e)); |
780 | 0 | return; |
781 | 0 | } |
782 | 11 | |
783 | 11 | std::unique_ptr<MemoryBuffer> newBuf = check(MemoryBuffer::getFile( |
784 | 11 | tmpName, /*FileSize*/ -1, /*RequiresNullTerminator*/ false)); |
785 | 11 | if ((*oldBuf)->getBuffer() != newBuf->getBuffer()) { |
786 | 2 | oldBuf->reset(); |
787 | 2 | handleError(errorCodeToError(sys::fs::rename(tmpName, path))); |
788 | 9 | } else { |
789 | 9 | sys::fs::remove(tmpName); |
790 | 9 | } |
791 | 11 | } |
792 | | |
793 | 28 | static void parseModuleDefs(StringRef path) { |
794 | 28 | std::unique_ptr<MemoryBuffer> mb = CHECK( |
795 | 28 | MemoryBuffer::getFile(path, -1, false, true), "could not open " + path); |
796 | 28 | COFFModuleDefinition m = check(parseCOFFModuleDefinition( |
797 | 28 | mb->getMemBufferRef(), config->machine, config->mingw)); |
798 | 28 | |
799 | 28 | if (config->outputFile.empty()) |
800 | 3 | config->outputFile = saver.save(m.OutputFile); |
801 | 28 | config->importName = saver.save(m.ImportName); |
802 | 28 | if (m.ImageBase) |
803 | 0 | config->imageBase = m.ImageBase; |
804 | 28 | if (m.StackReserve) |
805 | 2 | config->stackReserve = m.StackReserve; |
806 | 28 | if (m.StackCommit) |
807 | 1 | config->stackCommit = m.StackCommit; |
808 | 28 | if (m.HeapReserve) |
809 | 2 | config->heapReserve = m.HeapReserve; |
810 | 28 | if (m.HeapCommit) |
811 | 1 | config->heapCommit = m.HeapCommit; |
812 | 28 | if (m.MajorImageVersion) |
813 | 0 | config->majorImageVersion = m.MajorImageVersion; |
814 | 28 | if (m.MinorImageVersion) |
815 | 0 | config->minorImageVersion = m.MinorImageVersion; |
816 | 28 | if (m.MajorOSVersion) |
817 | 0 | config->majorOSVersion = m.MajorOSVersion; |
818 | 28 | if (m.MinorOSVersion) |
819 | 0 | config->minorOSVersion = m.MinorOSVersion; |
820 | 28 | |
821 | 34 | for (COFFShortExport e1 : m.Exports) { |
822 | 34 | Export e2; |
823 | 34 | // In simple cases, only Name is set. Renamed exports are parsed |
824 | 34 | // and set as "ExtName = Name". If Name has the form "OtherDll.Func", |
825 | 34 | // it shouldn't be a normal exported function but a forward to another |
826 | 34 | // DLL instead. This is supported by both MS and GNU linkers. |
827 | 34 | if (e1.ExtName != e1.Name && StringRef(e1.Name).contains('.')) { |
828 | 1 | e2.name = saver.save(e1.ExtName); |
829 | 1 | e2.forwardTo = saver.save(e1.Name); |
830 | 1 | config->exports.push_back(e2); |
831 | 1 | continue; |
832 | 1 | } |
833 | 33 | e2.name = saver.save(e1.Name); |
834 | 33 | e2.extName = saver.save(e1.ExtName); |
835 | 33 | e2.ordinal = e1.Ordinal; |
836 | 33 | e2.noname = e1.Noname; |
837 | 33 | e2.data = e1.Data; |
838 | 33 | e2.isPrivate = e1.Private; |
839 | 33 | e2.constant = e1.Constant; |
840 | 33 | config->exports.push_back(e2); |
841 | 33 | } |
842 | 28 | } |
843 | | |
844 | 1.13k | void LinkerDriver::enqueueTask(std::function<void()> task) { |
845 | 1.13k | taskQueue.push_back(std::move(task)); |
846 | 1.13k | } |
847 | | |
848 | 1.94k | bool LinkerDriver::run() { |
849 | 1.94k | ScopedTimer t(inputFileTimer); |
850 | 1.94k | |
851 | 1.94k | bool didWork = !taskQueue.empty(); |
852 | 3.08k | while (!taskQueue.empty()) { |
853 | 1.13k | taskQueue.front()(); |
854 | 1.13k | taskQueue.pop_front(); |
855 | 1.13k | } |
856 | 1.94k | return didWork; |
857 | 1.94k | } |
858 | | |
859 | | // Parse an /order file. If an option is given, the linker places |
860 | | // COMDAT sections in the same order as their names appear in the |
861 | | // given file. |
862 | 10 | static void parseOrderFile(StringRef arg) { |
863 | 10 | // For some reason, the MSVC linker requires a filename to be |
864 | 10 | // preceded by "@". |
865 | 10 | if (!arg.startswith("@")) { |
866 | 0 | error("malformed /order option: '@' missing"); |
867 | 0 | return; |
868 | 0 | } |
869 | 10 | |
870 | 10 | // Get a list of all comdat sections for error checking. |
871 | 10 | DenseSet<StringRef> set; |
872 | 10 | for (Chunk *c : symtab->getChunks()) |
873 | 30 | if (auto *sec = dyn_cast<SectionChunk>(c)) |
874 | 30 | if (sec->sym) |
875 | 20 | set.insert(sec->sym->getName()); |
876 | 10 | |
877 | 10 | // Open a file. |
878 | 10 | StringRef path = arg.substr(1); |
879 | 10 | std::unique_ptr<MemoryBuffer> mb = CHECK( |
880 | 10 | MemoryBuffer::getFile(path, -1, false, true), "could not open " + path); |
881 | 10 | |
882 | 10 | // Parse a file. An order file contains one symbol per line. |
883 | 10 | // All symbols that were not present in a given order file are |
884 | 10 | // considered to have the lowest priority 0 and are placed at |
885 | 10 | // end of an output section. |
886 | 18 | for (std::string s : args::getLines(mb->getMemBufferRef())) { |
887 | 18 | if (config->machine == I386 && !isDecorated(s)2 ) |
888 | 2 | s = "_" + s; |
889 | 18 | |
890 | 18 | if (set.count(s) == 0) { |
891 | 4 | if (config->warnMissingOrderSymbol) |
892 | 2 | warn("/order:" + arg + ": missing symbol: " + s + " [LNK4037]"); |
893 | 4 | } |
894 | 14 | else |
895 | 14 | config->order[s] = INT_MIN + config->order.size(); |
896 | 18 | } |
897 | 10 | } |
898 | | |
899 | 5.73k | static void markAddrsig(Symbol *s) { |
900 | 5.73k | if (auto *d = dyn_cast_or_null<Defined>(s)) |
901 | 3.39k | if (SectionChunk *c = dyn_cast_or_null<SectionChunk>(d->getChunk())) |
902 | 3.19k | c->keepUnique = true; |
903 | 5.73k | } |
904 | | |
905 | 436 | static void findKeepUniqueSections() { |
906 | 436 | // Exported symbols could be address-significant in other executables or DSOs, |
907 | 436 | // so we conservatively mark them as address-significant. |
908 | 436 | for (Export &r : config->exports) |
909 | 186 | markAddrsig(r.sym); |
910 | 436 | |
911 | 436 | // Visit the address-significance table in each object file and mark each |
912 | 436 | // referenced symbol as address-significant. |
913 | 573 | for (ObjFile *obj : ObjFile::instances) { |
914 | 573 | ArrayRef<Symbol *> syms = obj->getSymbols(); |
915 | 573 | if (obj->addrsigSec) { |
916 | 3 | ArrayRef<uint8_t> contents; |
917 | 3 | cantFail( |
918 | 3 | obj->getCOFFObj()->getSectionContents(obj->addrsigSec, contents)); |
919 | 3 | const uint8_t *cur = contents.begin(); |
920 | 7 | while (cur != contents.end()) { |
921 | 4 | unsigned size; |
922 | 4 | const char *err; |
923 | 4 | uint64_t symIndex = decodeULEB128(cur, &size, contents.end(), &err); |
924 | 4 | if (err) |
925 | 0 | fatal(toString(obj) + ": could not decode addrsig section: " + err); |
926 | 4 | if (symIndex >= syms.size()) |
927 | 0 | fatal(toString(obj) + ": invalid symbol index in addrsig section"); |
928 | 4 | markAddrsig(syms[symIndex]); |
929 | 4 | cur += size; |
930 | 4 | } |
931 | 570 | } else { |
932 | 570 | // If an object file does not have an address-significance table, |
933 | 570 | // conservatively mark all of its symbols as address-significant. |
934 | 570 | for (Symbol *s : syms) |
935 | 5.54k | markAddrsig(s); |
936 | 570 | } |
937 | 573 | } |
938 | 436 | } |
939 | | |
940 | | // link.exe replaces each %foo% in altPath with the contents of environment |
941 | | // variable foo, and adds the two magic env vars _PDB (expands to the basename |
942 | | // of pdb's output path) and _EXT (expands to the extension of the output |
943 | | // binary). |
944 | | // lld only supports %_PDB% and %_EXT% and warns on references to all other env |
945 | | // vars. |
946 | 13 | static void parsePDBAltPath(StringRef altPath) { |
947 | 13 | SmallString<128> buf; |
948 | 13 | StringRef pdbBasename = |
949 | 13 | sys::path::filename(config->pdbPath, sys::path::Style::windows); |
950 | 13 | StringRef binaryExtension = |
951 | 13 | sys::path::extension(config->outputFile, sys::path::Style::windows); |
952 | 13 | if (!binaryExtension.empty()) |
953 | 13 | binaryExtension = binaryExtension.substr(1); // %_EXT% does not include '.'. |
954 | 13 | |
955 | 13 | // Invariant: |
956 | 13 | // +--------- cursor ('a...' might be the empty string). |
957 | 13 | // | +----- firstMark |
958 | 13 | // | | +- secondMark |
959 | 13 | // v v v |
960 | 13 | // a...%...%... |
961 | 13 | size_t cursor = 0; |
962 | 22 | while (cursor < altPath.size()) { |
963 | 20 | size_t firstMark, secondMark; |
964 | 20 | if ((firstMark = altPath.find('%', cursor)) == StringRef::npos || |
965 | 20 | (secondMark = altPath.find('%', firstMark + 1)) == StringRef::npos12 ) { |
966 | 11 | // Didn't find another full fragment, treat rest of string as literal. |
967 | 11 | buf.append(altPath.substr(cursor)); |
968 | 11 | break; |
969 | 11 | } |
970 | 9 | |
971 | 9 | // Found a full fragment. Append text in front of first %, and interpret |
972 | 9 | // text between first and second % as variable name. |
973 | 9 | buf.append(altPath.substr(cursor, firstMark - cursor)); |
974 | 9 | StringRef var = altPath.substr(firstMark, secondMark - firstMark + 1); |
975 | 9 | if (var.equals_lower("%_pdb%")) |
976 | 4 | buf.append(pdbBasename); |
977 | 5 | else if (var.equals_lower("%_ext%")) |
978 | 3 | buf.append(binaryExtension); |
979 | 2 | else { |
980 | 2 | warn("only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping " + |
981 | 2 | var + " as literal"); |
982 | 2 | buf.append(var); |
983 | 2 | } |
984 | 9 | |
985 | 9 | cursor = secondMark + 1; |
986 | 9 | } |
987 | 13 | |
988 | 13 | config->pdbAltPath = buf; |
989 | 13 | } |
990 | | |
991 | | /// Check that at most one resource obj file was used. |
992 | | /// Call after ObjFile::Instances is complete. |
993 | 576 | static void diagnoseMultipleResourceObjFiles() { |
994 | 576 | // The .rsrc$01 section in a resource obj file contains a tree description |
995 | 576 | // of resources. Merging multiple resource obj files would require merging |
996 | 576 | // the trees instead of using usual linker section merging semantics. |
997 | 576 | // Since link.exe disallows linking more than one resource obj file with |
998 | 576 | // LNK4078, mirror that. The normal use of resource files is to give the |
999 | 576 | // linker many .res files, which are then converted to a single resource obj |
1000 | 576 | // file internally, so this is not a big restriction in practice. |
1001 | 576 | ObjFile *resourceObjFile = nullptr; |
1002 | 754 | for (ObjFile *f : ObjFile::instances) { |
1003 | 754 | if (!f->isResourceObjFile) |
1004 | 744 | continue; |
1005 | 10 | |
1006 | 10 | if (!resourceObjFile) { |
1007 | 8 | resourceObjFile = f; |
1008 | 8 | continue; |
1009 | 8 | } |
1010 | 2 | |
1011 | 2 | error(toString(f) + |
1012 | 2 | ": more than one resource obj file not allowed, already got " + |
1013 | 2 | toString(resourceObjFile)); |
1014 | 2 | } |
1015 | 576 | } |
1016 | | |
1017 | | // In MinGW, if no symbols are chosen to be exported, then all symbols are |
1018 | | // automatically exported by default. This behavior can be forced by the |
1019 | | // -export-all-symbols option, so that it happens even when exports are |
1020 | | // explicitly specified. The automatic behavior can be disabled using the |
1021 | | // -exclude-all-symbols option, so that lld-link behaves like link.exe rather |
1022 | | // than MinGW in the case that nothing is explicitly exported. |
1023 | 46 | void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) { |
1024 | 46 | if (!config->dll) |
1025 | 26 | return; |
1026 | 20 | |
1027 | 20 | if (!args.hasArg(OPT_export_all_symbols)) { |
1028 | 19 | if (!config->exports.empty()) |
1029 | 4 | return; |
1030 | 15 | if (args.hasArg(OPT_exclude_all_symbols)) |
1031 | 1 | return; |
1032 | 15 | } |
1033 | 15 | |
1034 | 15 | AutoExporter exporter; |
1035 | 15 | |
1036 | 15 | for (auto *arg : args.filtered(OPT_wholearchive_file)) |
1037 | 1 | if (Optional<StringRef> path = doFindFile(arg->getValue())) |
1038 | 1 | exporter.addWholeArchive(*path); |
1039 | 15 | |
1040 | 263 | symtab->forEachSymbol([&](Symbol *s) { |
1041 | 263 | auto *def = dyn_cast<Defined>(s); |
1042 | 263 | if (!exporter.shouldExport(def)) |
1043 | 238 | return; |
1044 | 25 | |
1045 | 25 | Export e; |
1046 | 25 | e.name = def->getName(); |
1047 | 25 | e.sym = def; |
1048 | 25 | if (Chunk *c = def->getChunk()) |
1049 | 25 | if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)) |
1050 | 7 | e.data = true; |
1051 | 25 | config->exports.push_back(e); |
1052 | 25 | }); |
1053 | 15 | } |
1054 | | |
1055 | 689 | void LinkerDriver::link(ArrayRef<const char *> argsArr) { |
1056 | 689 | // Needed for LTO. |
1057 | 689 | InitializeAllTargetInfos(); |
1058 | 689 | InitializeAllTargets(); |
1059 | 689 | InitializeAllTargetMCs(); |
1060 | 689 | InitializeAllAsmParsers(); |
1061 | 689 | InitializeAllAsmPrinters(); |
1062 | 689 | |
1063 | 689 | // If the first command line argument is "/lib", link.exe acts like lib.exe. |
1064 | 689 | // We call our own implementation of lib.exe that understands bitcode files. |
1065 | 689 | if (argsArr.size() > 1 && StringRef(argsArr[1]).equals_lower("/lib")687 ) { |
1066 | 4 | if (llvm::libDriverMain(argsArr.slice(1)) != 0) |
1067 | 0 | fatal("lib failed"); |
1068 | 4 | return; |
1069 | 4 | } |
1070 | 685 | |
1071 | 685 | // Parse command line options. |
1072 | 685 | ArgParser parser; |
1073 | 685 | opt::InputArgList args = parser.parseLINK(argsArr); |
1074 | 685 | |
1075 | 685 | // Parse and evaluate -mllvm options. |
1076 | 685 | std::vector<const char *> v; |
1077 | 685 | v.push_back("lld-link (LLVM option parsing)"); |
1078 | 685 | for (auto *arg : args.filtered(OPT_mllvm)) |
1079 | 2 | v.push_back(arg->getValue()); |
1080 | 685 | cl::ParseCommandLineOptions(v.size(), v.data()); |
1081 | 685 | |
1082 | 685 | // Handle /errorlimit early, because error() depends on it. |
1083 | 685 | if (auto *arg = args.getLastArg(OPT_errorlimit)) { |
1084 | 3 | int n = 20; |
1085 | 3 | StringRef s = arg->getValue(); |
1086 | 3 | if (s.getAsInteger(10, n)) |
1087 | 1 | error(arg->getSpelling() + " number expected, but got " + s); |
1088 | 3 | errorHandler().errorLimit = n; |
1089 | 3 | } |
1090 | 685 | |
1091 | 685 | // Handle /help |
1092 | 685 | if (args.hasArg(OPT_help)) { |
1093 | 3 | printHelp(argsArr[0]); |
1094 | 3 | return; |
1095 | 3 | } |
1096 | 682 | |
1097 | 682 | lld::threadsEnabled = args.hasFlag(OPT_threads, OPT_threads_no, true); |
1098 | 682 | |
1099 | 682 | if (args.hasArg(OPT_show_timing)) |
1100 | 0 | config->showTiming = true; |
1101 | 682 | |
1102 | 682 | config->showSummary = args.hasArg(OPT_summary); |
1103 | 682 | |
1104 | 682 | ScopedTimer t(Timer::root()); |
1105 | 682 | // Handle --version, which is an lld extension. This option is a bit odd |
1106 | 682 | // because it doesn't start with "/", but we deliberately chose "--" to |
1107 | 682 | // avoid conflict with /version and for compatibility with clang-cl. |
1108 | 682 | if (args.hasArg(OPT_dash_dash_version)) { |
1109 | 1 | outs() << getLLDVersion() << "\n"; |
1110 | 1 | return; |
1111 | 1 | } |
1112 | 681 | |
1113 | 681 | // Handle /lldmingw early, since it can potentially affect how other |
1114 | 681 | // options are handled. |
1115 | 681 | config->mingw = args.hasArg(OPT_lldmingw); |
1116 | 681 | |
1117 | 681 | if (auto *arg = args.getLastArg(OPT_linkrepro)) { |
1118 | 4 | SmallString<64> path = StringRef(arg->getValue()); |
1119 | 4 | sys::path::append(path, "repro.tar"); |
1120 | 4 | |
1121 | 4 | Expected<std::unique_ptr<TarWriter>> errOrWriter = |
1122 | 4 | TarWriter::create(path, "repro"); |
1123 | 4 | |
1124 | 4 | if (errOrWriter) { |
1125 | 4 | tar = std::move(*errOrWriter); |
1126 | 4 | } else { |
1127 | 0 | error("/linkrepro: failed to open " + path + ": " + |
1128 | 0 | toString(errOrWriter.takeError())); |
1129 | 0 | } |
1130 | 4 | } |
1131 | 681 | |
1132 | 681 | if (!args.hasArg(OPT_INPUT)) { |
1133 | 8 | if (args.hasArg(OPT_deffile)) |
1134 | 8 | config->noEntry = true; |
1135 | 0 | else |
1136 | 0 | fatal("no input files"); |
1137 | 681 | } |
1138 | 681 | |
1139 | 681 | // Construct search path list. |
1140 | 681 | searchPaths.push_back(""); |
1141 | 681 | for (auto *arg : args.filtered(OPT_libpath)) |
1142 | 12 | searchPaths.push_back(arg->getValue()); |
1143 | 681 | addLibSearchPaths(); |
1144 | 681 | |
1145 | 681 | // Handle /ignore |
1146 | 681 | for (auto *arg : args.filtered(OPT_ignore)) { |
1147 | 6 | SmallVector<StringRef, 8> vec; |
1148 | 6 | StringRef(arg->getValue()).split(vec, ','); |
1149 | 8 | for (StringRef s : vec) { |
1150 | 8 | if (s == "4037") |
1151 | 3 | config->warnMissingOrderSymbol = false; |
1152 | 5 | else if (s == "4099") |
1153 | 3 | config->warnDebugInfoUnusable = false; |
1154 | 2 | else if (s == "4217") |
1155 | 2 | config->warnLocallyDefinedImported = false; |
1156 | 8 | // Other warning numbers are ignored. |
1157 | 8 | } |
1158 | 6 | } |
1159 | 681 | |
1160 | 681 | // Handle /out |
1161 | 681 | if (auto *arg = args.getLastArg(OPT_out)) |
1162 | 619 | config->outputFile = arg->getValue(); |
1163 | 681 | |
1164 | 681 | // Handle /verbose |
1165 | 681 | if (args.hasArg(OPT_verbose)) |
1166 | 58 | config->verbose = true; |
1167 | 681 | errorHandler().verbose = config->verbose; |
1168 | 681 | |
1169 | 681 | // Handle /force or /force:unresolved |
1170 | 681 | if (args.hasArg(OPT_force, OPT_force_unresolved)) |
1171 | 24 | config->forceUnresolved = true; |
1172 | 681 | |
1173 | 681 | // Handle /force or /force:multiple |
1174 | 681 | if (args.hasArg(OPT_force, OPT_force_multiple)) |
1175 | 25 | config->forceMultiple = true; |
1176 | 681 | |
1177 | 681 | // Handle /force or /force:multipleres |
1178 | 681 | if (args.hasArg(OPT_force, OPT_force_multipleres)) |
1179 | 25 | config->forceMultipleRes = true; |
1180 | 681 | |
1181 | 681 | // Handle /debug |
1182 | 681 | DebugKind debug = parseDebugKind(args); |
1183 | 681 | if (debug == DebugKind::Full || debug == DebugKind::Dwarf573 || |
1184 | 681 | debug == DebugKind::GHash562 ) { |
1185 | 121 | config->debug = true; |
1186 | 121 | config->incremental = true; |
1187 | 121 | } |
1188 | 681 | |
1189 | 681 | // Handle /demangle |
1190 | 681 | config->demangle = args.hasFlag(OPT_demangle, OPT_demangle_no); |
1191 | 681 | |
1192 | 681 | // Handle /debugtype |
1193 | 681 | config->debugTypes = parseDebugTypes(args); |
1194 | 681 | |
1195 | 681 | // Handle /pdb |
1196 | 681 | bool shouldCreatePDB = |
1197 | 681 | (debug == DebugKind::Full || debug == DebugKind::GHash573 ); |
1198 | 681 | if (shouldCreatePDB) { |
1199 | 110 | if (auto *arg = args.getLastArg(OPT_pdb)) |
1200 | 57 | config->pdbPath = arg->getValue(); |
1201 | 110 | if (auto *arg = args.getLastArg(OPT_pdbaltpath)) |
1202 | 13 | config->pdbAltPath = arg->getValue(); |
1203 | 110 | if (args.hasArg(OPT_natvis)) |
1204 | 0 | config->natvisFiles = args.getAllArgValues(OPT_natvis); |
1205 | 110 | |
1206 | 110 | if (auto *arg = args.getLastArg(OPT_pdb_source_path)) |
1207 | 2 | config->pdbSourcePath = arg->getValue(); |
1208 | 110 | } |
1209 | 681 | |
1210 | 681 | // Handle /noentry |
1211 | 681 | if (args.hasArg(OPT_noentry)) { |
1212 | 50 | if (args.hasArg(OPT_dll)) |
1213 | 50 | config->noEntry = true; |
1214 | 0 | else |
1215 | 0 | error("/noentry must be specified with /dll"); |
1216 | 50 | } |
1217 | 681 | |
1218 | 681 | // Handle /dll |
1219 | 681 | if (args.hasArg(OPT_dll)) { |
1220 | 185 | config->dll = true; |
1221 | 185 | config->manifestID = 2; |
1222 | 185 | } |
1223 | 681 | |
1224 | 681 | // Handle /dynamicbase and /fixed. We can't use hasFlag for /dynamicbase |
1225 | 681 | // because we need to explicitly check whether that option or its inverse was |
1226 | 681 | // present in the argument list in order to handle /fixed. |
1227 | 681 | auto *dynamicBaseArg = args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no); |
1228 | 681 | if (dynamicBaseArg && |
1229 | 681 | dynamicBaseArg->getOption().getID() == OPT_dynamicbase_no2 ) |
1230 | 2 | config->dynamicBase = false; |
1231 | 681 | |
1232 | 681 | // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the |
1233 | 681 | // default setting for any other project type.", but link.exe defaults to |
1234 | 681 | // /FIXED:NO for exe outputs as well. Match behavior, not docs. |
1235 | 681 | bool fixed = args.hasFlag(OPT_fixed, OPT_fixed_no, false); |
1236 | 681 | if (fixed) { |
1237 | 6 | if (dynamicBaseArg && |
1238 | 6 | dynamicBaseArg->getOption().getID() == OPT_dynamicbase0 ) { |
1239 | 0 | error("/fixed must not be specified with /dynamicbase"); |
1240 | 6 | } else { |
1241 | 6 | config->relocatable = false; |
1242 | 6 | config->dynamicBase = false; |
1243 | 6 | } |
1244 | 6 | } |
1245 | 681 | |
1246 | 681 | // Handle /appcontainer |
1247 | 681 | config->appContainer = |
1248 | 681 | args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false); |
1249 | 681 | |
1250 | 681 | // Handle /machine |
1251 | 681 | if (auto *arg = args.getLastArg(OPT_machine)) { |
1252 | 24 | config->machine = getMachineType(arg->getValue()); |
1253 | 24 | if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) |
1254 | 0 | fatal(Twine("unknown /machine argument: ") + arg->getValue()); |
1255 | 681 | } |
1256 | 681 | |
1257 | 681 | // Handle /nodefaultlib:<filename> |
1258 | 681 | for (auto *arg : args.filtered(OPT_nodefaultlib)) |
1259 | 4 | config->noDefaultLibs.insert(doFindLib(arg->getValue()).lower()); |
1260 | 681 | |
1261 | 681 | // Handle /nodefaultlib |
1262 | 681 | if (args.hasArg(OPT_nodefaultlib_all)) |
1263 | 121 | config->noDefaultLibAll = true; |
1264 | 681 | |
1265 | 681 | // Handle /base |
1266 | 681 | if (auto *arg = args.getLastArg(OPT_base)) |
1267 | 2 | parseNumbers(arg->getValue(), &config->imageBase); |
1268 | 681 | |
1269 | 681 | // Handle /filealign |
1270 | 681 | if (auto *arg = args.getLastArg(OPT_filealign)) { |
1271 | 1 | parseNumbers(arg->getValue(), &config->fileAlign); |
1272 | 1 | if (!isPowerOf2_64(config->fileAlign)) |
1273 | 0 | error("/filealign: not a power of two: " + Twine(config->fileAlign)); |
1274 | 1 | } |
1275 | 681 | |
1276 | 681 | // Handle /stack |
1277 | 681 | if (auto *arg = args.getLastArg(OPT_stack)) |
1278 | 2 | parseNumbers(arg->getValue(), &config->stackReserve, &config->stackCommit); |
1279 | 681 | |
1280 | 681 | // Handle /guard:cf |
1281 | 681 | if (auto *arg = args.getLastArg(OPT_guard)) |
1282 | 13 | parseGuard(arg->getValue()); |
1283 | 681 | |
1284 | 681 | // Handle /heap |
1285 | 681 | if (auto *arg = args.getLastArg(OPT_heap)) |
1286 | 3 | parseNumbers(arg->getValue(), &config->heapReserve, &config->heapCommit); |
1287 | 681 | |
1288 | 681 | // Handle /version |
1289 | 681 | if (auto *arg = args.getLastArg(OPT_version)) |
1290 | 2 | parseVersion(arg->getValue(), &config->majorImageVersion, |
1291 | 2 | &config->minorImageVersion); |
1292 | 681 | |
1293 | 681 | // Handle /subsystem |
1294 | 681 | if (auto *arg = args.getLastArg(OPT_subsystem)) |
1295 | 170 | parseSubsystem(arg->getValue(), &config->subsystem, &config->majorOSVersion, |
1296 | 170 | &config->minorOSVersion); |
1297 | 681 | |
1298 | 681 | // Handle /timestamp |
1299 | 681 | if (llvm::opt::Arg *arg = args.getLastArg(OPT_timestamp, OPT_repro)) { |
1300 | 5 | if (arg->getOption().getID() == OPT_repro) { |
1301 | 4 | config->timestamp = 0; |
1302 | 4 | config->repro = true; |
1303 | 4 | } else { |
1304 | 1 | config->repro = false; |
1305 | 1 | StringRef value(arg->getValue()); |
1306 | 1 | if (value.getAsInteger(0, config->timestamp)) |
1307 | 0 | fatal(Twine("invalid timestamp: ") + value + |
1308 | 0 | ". Expected 32-bit integer"); |
1309 | 676 | } |
1310 | 676 | } else { |
1311 | 676 | config->repro = false; |
1312 | 676 | config->timestamp = time(nullptr); |
1313 | 676 | } |
1314 | 681 | |
1315 | 681 | // Handle /alternatename |
1316 | 681 | for (auto *arg : args.filtered(OPT_alternatename)) |
1317 | 8 | parseAlternateName(arg->getValue()); |
1318 | 681 | |
1319 | 681 | // Handle /include |
1320 | 681 | for (auto *arg : args.filtered(OPT_incl)) |
1321 | 31 | addUndefined(arg->getValue()); |
1322 | 681 | |
1323 | 681 | // Handle /implib |
1324 | 681 | if (auto *arg = args.getLastArg(OPT_implib)) |
1325 | 30 | config->implib = arg->getValue(); |
1326 | 681 | |
1327 | 681 | // Handle /opt. |
1328 | 681 | bool doGC = debug == DebugKind::None || args.hasArg(OPT_profile)123 ; |
1329 | 681 | unsigned icfLevel = |
1330 | 681 | args.hasArg(OPT_profile) ? 07 : 1674 ; // 0: off, 1: limited, 2: on |
1331 | 681 | unsigned tailMerge = 1; |
1332 | 681 | for (auto *arg : args.filtered(OPT_opt)) { |
1333 | 79 | std::string str = StringRef(arg->getValue()).lower(); |
1334 | 79 | SmallVector<StringRef, 1> vec; |
1335 | 79 | StringRef(str).split(vec, ','); |
1336 | 95 | for (StringRef s : vec) { |
1337 | 95 | if (s == "ref") { |
1338 | 20 | doGC = true; |
1339 | 75 | } else if (s == "noref") { |
1340 | 36 | doGC = false; |
1341 | 39 | } else if (s == "icf" || s.startswith("icf=")22 ) { |
1342 | 17 | icfLevel = 2; |
1343 | 22 | } else if (s == "noicf") { |
1344 | 17 | icfLevel = 0; |
1345 | 17 | } else if (5 s == "lldtailmerge"5 ) { |
1346 | 1 | tailMerge = 2; |
1347 | 4 | } else if (s == "nolldtailmerge") { |
1348 | 1 | tailMerge = 0; |
1349 | 3 | } else if (s.startswith("lldlto=")) { |
1350 | 2 | StringRef optLevel = s.substr(7); |
1351 | 2 | if (optLevel.getAsInteger(10, config->ltoo) || config->ltoo > 3) |
1352 | 0 | error("/opt:lldlto: invalid optimization level: " + optLevel); |
1353 | 2 | } else if (1 s.startswith("lldltojobs=")1 ) { |
1354 | 0 | StringRef jobs = s.substr(11); |
1355 | 0 | if (jobs.getAsInteger(10, config->thinLTOJobs) || |
1356 | 0 | config->thinLTOJobs == 0) |
1357 | 0 | error("/opt:lldltojobs: invalid job count: " + jobs); |
1358 | 1 | } else if (s.startswith("lldltopartitions=")) { |
1359 | 1 | StringRef n = s.substr(17); |
1360 | 1 | if (n.getAsInteger(10, config->ltoPartitions) || |
1361 | 1 | config->ltoPartitions == 0) |
1362 | 0 | error("/opt:lldltopartitions: invalid partition count: " + n); |
1363 | 1 | } else if (0 s != "lbr"0 && s != "nolbr"0 ) |
1364 | 0 | error("/opt: unknown option: " + s); |
1365 | 95 | } |
1366 | 79 | } |
1367 | 681 | |
1368 | 681 | // Limited ICF is enabled if GC is enabled and ICF was never mentioned |
1369 | 681 | // explicitly. |
1370 | 681 | // FIXME: LLD only implements "limited" ICF, i.e. it only merges identical |
1371 | 681 | // code. If the user passes /OPT:ICF explicitly, LLD should merge identical |
1372 | 681 | // comdat readonly data. |
1373 | 681 | if (icfLevel == 1 && !doGC644 ) |
1374 | 120 | icfLevel = 0; |
1375 | 681 | config->doGC = doGC; |
1376 | 681 | config->doICF = icfLevel > 0; |
1377 | 681 | config->tailMerge = (tailMerge == 1 && config->doICF679 ) || tailMerge == 2141 ; |
1378 | 681 | |
1379 | 681 | // Handle /lldsavetemps |
1380 | 681 | if (args.hasArg(OPT_lldsavetemps)) |
1381 | 4 | config->saveTemps = true; |
1382 | 681 | |
1383 | 681 | // Handle /kill-at |
1384 | 681 | if (args.hasArg(OPT_kill_at)) |
1385 | 2 | config->killAt = true; |
1386 | 681 | |
1387 | 681 | // Handle /lldltocache |
1388 | 681 | if (auto *arg = args.getLastArg(OPT_lldltocache)) |
1389 | 1 | config->ltoCache = arg->getValue(); |
1390 | 681 | |
1391 | 681 | // Handle /lldsavecachepolicy |
1392 | 681 | if (auto *arg = args.getLastArg(OPT_lldltocachepolicy)) |
1393 | 1 | config->ltoCachePolicy = CHECK( |
1394 | 681 | parseCachePruningPolicy(arg->getValue()), |
1395 | 681 | Twine("/lldltocachepolicy: invalid cache policy: ") + arg->getValue()); |
1396 | 681 | |
1397 | 681 | // Handle /failifmismatch |
1398 | 681 | for (auto *arg : args.filtered(OPT_failifmismatch)) |
1399 | 4 | checkFailIfMismatch(arg->getValue(), nullptr); |
1400 | 681 | |
1401 | 681 | // Handle /merge |
1402 | 681 | for (auto *arg : args.filtered(OPT_merge)) |
1403 | 12 | parseMerge(arg->getValue()); |
1404 | 681 | |
1405 | 681 | // Add default section merging rules after user rules. User rules take |
1406 | 681 | // precedence, but we will emit a warning if there is a conflict. |
1407 | 681 | parseMerge(".idata=.rdata"); |
1408 | 681 | parseMerge(".didat=.rdata"); |
1409 | 681 | parseMerge(".edata=.rdata"); |
1410 | 681 | parseMerge(".xdata=.rdata"); |
1411 | 681 | parseMerge(".bss=.data"); |
1412 | 681 | |
1413 | 681 | if (config->mingw) { |
1414 | 48 | parseMerge(".ctors=.rdata"); |
1415 | 48 | parseMerge(".dtors=.rdata"); |
1416 | 48 | parseMerge(".CRT=.rdata"); |
1417 | 48 | } |
1418 | 681 | |
1419 | 681 | // Handle /section |
1420 | 681 | for (auto *arg : args.filtered(OPT_section)) |
1421 | 6 | parseSection(arg->getValue()); |
1422 | 681 | |
1423 | 681 | // Handle /aligncomm |
1424 | 681 | for (auto *arg : args.filtered(OPT_aligncomm)) |
1425 | 0 | parseAligncomm(arg->getValue()); |
1426 | 681 | |
1427 | 681 | // Handle /manifestdependency. This enables /manifest unless /manifest:no is |
1428 | 681 | // also passed. |
1429 | 681 | if (auto *arg = args.getLastArg(OPT_manifestdependency)) { |
1430 | 2 | config->manifestDependency = arg->getValue(); |
1431 | 2 | config->manifest = Configuration::SideBySide; |
1432 | 2 | } |
1433 | 681 | |
1434 | 681 | // Handle /manifest and /manifest: |
1435 | 681 | if (auto *arg = args.getLastArg(OPT_manifest, OPT_manifest_colon)) { |
1436 | 5 | if (arg->getOption().getID() == OPT_manifest) |
1437 | 4 | config->manifest = Configuration::SideBySide; |
1438 | 1 | else |
1439 | 1 | parseManifest(arg->getValue()); |
1440 | 5 | } |
1441 | 681 | |
1442 | 681 | // Handle /manifestuac |
1443 | 681 | if (auto *arg = args.getLastArg(OPT_manifestuac)) |
1444 | 5 | parseManifestUAC(arg->getValue()); |
1445 | 681 | |
1446 | 681 | // Handle /manifestfile |
1447 | 681 | if (auto *arg = args.getLastArg(OPT_manifestfile)) |
1448 | 0 | config->manifestFile = arg->getValue(); |
1449 | 681 | |
1450 | 681 | // Handle /manifestinput |
1451 | 681 | for (auto *arg : args.filtered(OPT_manifestinput)) |
1452 | 1 | config->manifestInput.push_back(arg->getValue()); |
1453 | 681 | |
1454 | 681 | if (!config->manifestInput.empty() && |
1455 | 681 | config->manifest != Configuration::Embed1 ) { |
1456 | 0 | fatal("/manifestinput: requires /manifest:embed"); |
1457 | 0 | } |
1458 | 681 | |
1459 | 681 | config->thinLTOEmitImportsFiles = args.hasArg(OPT_thinlto_emit_imports_files); |
1460 | 681 | config->thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) || |
1461 | 681 | args.hasArg(OPT_thinlto_index_only_arg)672 ; |
1462 | 681 | config->thinLTOIndexOnlyArg = |
1463 | 681 | args.getLastArgValue(OPT_thinlto_index_only_arg); |
1464 | 681 | config->thinLTOPrefixReplace = |
1465 | 681 | getOldNewOptions(args, OPT_thinlto_prefix_replace); |
1466 | 681 | config->thinLTOObjectSuffixReplace = |
1467 | 681 | getOldNewOptions(args, OPT_thinlto_object_suffix_replace); |
1468 | 681 | // Handle miscellaneous boolean flags. |
1469 | 681 | config->allowBind = args.hasFlag(OPT_allowbind, OPT_allowbind_no, true); |
1470 | 681 | config->allowIsolation = |
1471 | 681 | args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true); |
1472 | 681 | config->incremental = |
1473 | 681 | args.hasFlag(OPT_incremental, OPT_incremental_no, |
1474 | 681 | !config->doGC && !config->doICF139 && !args.hasArg(OPT_order)132 && |
1475 | 681 | !args.hasArg(OPT_profile)122 ); |
1476 | 681 | config->integrityCheck = |
1477 | 681 | args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false); |
1478 | 681 | config->nxCompat = args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true); |
1479 | 681 | for (auto *arg : args.filtered(OPT_swaprun)) |
1480 | 11 | parseSwaprun(arg->getValue()); |
1481 | 681 | config->terminalServerAware = |
1482 | 681 | !config->dll && args.hasFlag(OPT_tsaware, OPT_tsaware_no, true)496 ; |
1483 | 681 | config->debugDwarf = debug == DebugKind::Dwarf; |
1484 | 681 | config->debugGHashes = debug == DebugKind::GHash; |
1485 | 681 | config->debugSymtab = debug == DebugKind::Symtab; |
1486 | 681 | |
1487 | 681 | config->mapFile = getMapFile(args); |
1488 | 681 | |
1489 | 681 | if (config->incremental && args.hasArg(OPT_profile)125 ) { |
1490 | 2 | warn("ignoring '/incremental' due to '/profile' specification"); |
1491 | 2 | config->incremental = false; |
1492 | 2 | } |
1493 | 681 | |
1494 | 681 | if (config->incremental && args.hasArg(OPT_order)123 ) { |
1495 | 2 | warn("ignoring '/incremental' due to '/order' specification"); |
1496 | 2 | config->incremental = false; |
1497 | 2 | } |
1498 | 681 | |
1499 | 681 | if (config->incremental && config->doGC121 ) { |
1500 | 4 | warn("ignoring '/incremental' because REF is enabled; use '/opt:noref' to " |
1501 | 4 | "disable"); |
1502 | 4 | config->incremental = false; |
1503 | 4 | } |
1504 | 681 | |
1505 | 681 | if (config->incremental && config->doICF117 ) { |
1506 | 2 | warn("ignoring '/incremental' because ICF is enabled; use '/opt:noicf' to " |
1507 | 2 | "disable"); |
1508 | 2 | config->incremental = false; |
1509 | 2 | } |
1510 | 681 | |
1511 | 681 | if (errorCount()) |
1512 | 14 | return; |
1513 | 667 | |
1514 | 667 | std::set<sys::fs::UniqueID> wholeArchives; |
1515 | 667 | for (auto *arg : args.filtered(OPT_wholearchive_file)) |
1516 | 4 | if (Optional<StringRef> path = doFindFile(arg->getValue())) |
1517 | 4 | if (Optional<sys::fs::UniqueID> id = getUniqueID(*path)) |
1518 | 4 | wholeArchives.insert(*id); |
1519 | 667 | |
1520 | 667 | // A predicate returning true if a given path is an argument for |
1521 | 667 | // /wholearchive:, or /wholearchive is enabled globally. |
1522 | 667 | // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj" |
1523 | 667 | // needs to be handled as "/wholearchive:foo.obj foo.obj". |
1524 | 962 | auto isWholeArchive = [&](StringRef path) -> bool { |
1525 | 962 | if (args.hasArg(OPT_wholearchive_flag)) |
1526 | 2 | return true; |
1527 | 960 | if (Optional<sys::fs::UniqueID> id = getUniqueID(path)) |
1528 | 892 | return wholeArchives.count(*id); |
1529 | 68 | return false; |
1530 | 68 | }; |
1531 | 667 | |
1532 | 667 | // Create a list of input files. Files can be given as arguments |
1533 | 667 | // for /defaultlib option. |
1534 | 667 | for (auto *arg : args.filtered(OPT_INPUT, OPT_wholearchive_file)) |
1535 | 966 | if (Optional<StringRef> path = findFile(arg->getValue())) |
1536 | 962 | enqueuePath(*path, isWholeArchive(*path)); |
1537 | 667 | |
1538 | 667 | for (auto *arg : args.filtered(OPT_defaultlib)) |
1539 | 9 | if (Optional<StringRef> path = findLib(arg->getValue())) |
1540 | 7 | enqueuePath(*path, false); |
1541 | 667 | |
1542 | 667 | // Windows specific -- Create a resource file containing a manifest file. |
1543 | 667 | if (config->manifest == Configuration::Embed) |
1544 | 1 | addBuffer(createManifestRes(), false); |
1545 | 667 | |
1546 | 667 | // Read all input files given via the command line. |
1547 | 667 | run(); |
1548 | 667 | |
1549 | 667 | if (errorCount()) |
1550 | 40 | return; |
1551 | 627 | |
1552 | 627 | // We should have inferred a machine type by now from the input files, but if |
1553 | 627 | // not we assume x64. |
1554 | 627 | if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) { |
1555 | 4 | warn("/machine is not specified. x64 is assumed"); |
1556 | 4 | config->machine = AMD64; |
1557 | 4 | } |
1558 | 627 | config->wordsize = config->is64() ? 8505 : 4122 ; |
1559 | 627 | |
1560 | 627 | // Handle /safeseh, x86 only, on by default, except for mingw. |
1561 | 627 | if (config->machine == I386 && |
1562 | 627 | args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw)103 ) |
1563 | 48 | config->safeSEH = true; |
1564 | 627 | |
1565 | 627 | // Handle /functionpadmin |
1566 | 627 | for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt)) |
1567 | 12 | parseFunctionPadMin(arg, config->machine); |
1568 | 627 | |
1569 | 627 | // Input files can be Windows resource files (.res files). We use |
1570 | 627 | // WindowsResource to convert resource files to a regular COFF file, |
1571 | 627 | // then link the resulting file normally. |
1572 | 627 | if (!resources.empty()) |
1573 | 8 | symtab->addFile(make<ObjFile>(convertResToCOFF(resources))); |
1574 | 627 | |
1575 | 627 | if (tar) |
1576 | 4 | tar->append("response.txt", |
1577 | 4 | createResponseFile(args, filePaths, |
1578 | 4 | ArrayRef<StringRef>(searchPaths).slice(1))); |
1579 | 627 | |
1580 | 627 | // Handle /largeaddressaware |
1581 | 627 | config->largeAddressAware = args.hasFlag( |
1582 | 627 | OPT_largeaddressaware, OPT_largeaddressaware_no, config->is64()); |
1583 | 627 | |
1584 | 627 | // Handle /highentropyva |
1585 | 627 | config->highEntropyVA = |
1586 | 627 | config->is64() && |
1587 | 627 | args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true)505 ; |
1588 | 627 | |
1589 | 627 | if (!config->dynamicBase && |
1590 | 627 | (7 config->machine == ARMNT7 || config->machine == ARM646 )) |
1591 | 2 | error("/dynamicbase:no is not compatible with " + |
1592 | 2 | machineToStr(config->machine)); |
1593 | 627 | |
1594 | 627 | // Handle /export |
1595 | 627 | for (auto *arg : args.filtered(OPT_export)) { |
1596 | 54 | Export e = parseExport(arg->getValue()); |
1597 | 54 | if (config->machine == I386) { |
1598 | 18 | if (!isDecorated(e.name)) |
1599 | 18 | e.name = saver.save("_" + e.name); |
1600 | 18 | if (!e.extName.empty() && !isDecorated(e.extName)5 ) |
1601 | 5 | e.extName = saver.save("_" + e.extName); |
1602 | 18 | } |
1603 | 54 | config->exports.push_back(e); |
1604 | 54 | } |
1605 | 627 | |
1606 | 627 | // Handle /def |
1607 | 627 | if (auto *arg = args.getLastArg(OPT_deffile)) { |
1608 | 28 | // parseModuleDefs mutates Config object. |
1609 | 28 | parseModuleDefs(arg->getValue()); |
1610 | 28 | } |
1611 | 627 | |
1612 | 627 | // Handle generation of import library from a def file. |
1613 | 627 | if (!args.hasArg(OPT_INPUT)) { |
1614 | 8 | fixupExports(); |
1615 | 8 | createImportLibrary(/*asLib=*/true); |
1616 | 8 | return; |
1617 | 8 | } |
1618 | 619 | |
1619 | 619 | // Windows specific -- if no /subsystem is given, we need to infer |
1620 | 619 | // that from entry point name. Must happen before /entry handling, |
1621 | 619 | // and after the early return when just writing an import library. |
1622 | 619 | if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN) { |
1623 | 459 | config->subsystem = inferSubsystem(); |
1624 | 459 | if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN) |
1625 | 0 | fatal("subsystem must be defined"); |
1626 | 619 | } |
1627 | 619 | |
1628 | 619 | // Handle /entry and /dll |
1629 | 619 | if (auto *arg = args.getLastArg(OPT_entry)) { |
1630 | 454 | config->entry = addUndefined(mangle(arg->getValue())); |
1631 | 454 | } else if (165 !config->entry165 && !config->noEntry164 ) { |
1632 | 124 | if (args.hasArg(OPT_dll)) { |
1633 | 67 | StringRef s = (config->machine == I386) ? "__DllMainCRTStartup@12"10 |
1634 | 67 | : "_DllMainCRTStartup"57 ; |
1635 | 67 | config->entry = addUndefined(s); |
1636 | 67 | } else { |
1637 | 57 | // Windows specific -- If entry point name is not given, we need to |
1638 | 57 | // infer that from user-defined entry name. |
1639 | 57 | StringRef s = findDefaultEntry(); |
1640 | 57 | if (s.empty()) |
1641 | 0 | fatal("entry point must be defined"); |
1642 | 57 | config->entry = addUndefined(s); |
1643 | 57 | log("Entry name inferred: " + s); |
1644 | 57 | } |
1645 | 124 | } |
1646 | 619 | |
1647 | 619 | // Handle /delayload |
1648 | 619 | for (auto *arg : args.filtered(OPT_delayload)) { |
1649 | 6 | config->delayLoads.insert(StringRef(arg->getValue()).lower()); |
1650 | 6 | if (config->machine == I386) { |
1651 | 1 | config->delayLoadHelper = addUndefined("___delayLoadHelper2@8"); |
1652 | 5 | } else { |
1653 | 5 | config->delayLoadHelper = addUndefined("__delayLoadHelper2"); |
1654 | 5 | } |
1655 | 6 | } |
1656 | 619 | |
1657 | 619 | // Set default image name if neither /out or /def set it. |
1658 | 619 | if (config->outputFile.empty()) { |
1659 | 35 | config->outputFile = |
1660 | 35 | getOutputPath((*args.filtered(OPT_INPUT).begin())->getValue()); |
1661 | 35 | } |
1662 | 619 | |
1663 | 619 | // Fail early if an output file is not writable. |
1664 | 619 | if (auto e = tryCreateFile(config->outputFile)) { |
1665 | 1 | error("cannot open output file " + config->outputFile + ": " + e.message()); |
1666 | 1 | return; |
1667 | 1 | } |
1668 | 618 | |
1669 | 618 | if (shouldCreatePDB) { |
1670 | 110 | // Put the PDB next to the image if no /pdb flag was passed. |
1671 | 110 | if (config->pdbPath.empty()) { |
1672 | 53 | config->pdbPath = config->outputFile; |
1673 | 53 | sys::path::replace_extension(config->pdbPath, ".pdb"); |
1674 | 53 | } |
1675 | 110 | |
1676 | 110 | // The embedded PDB path should be the absolute path to the PDB if no |
1677 | 110 | // /pdbaltpath flag was passed. |
1678 | 110 | if (config->pdbAltPath.empty()) { |
1679 | 97 | config->pdbAltPath = config->pdbPath; |
1680 | 97 | |
1681 | 97 | // It's important to make the path absolute and remove dots. This path |
1682 | 97 | // will eventually be written into the PE header, and certain Microsoft |
1683 | 97 | // tools won't work correctly if these assumptions are not held. |
1684 | 97 | sys::fs::make_absolute(config->pdbAltPath); |
1685 | 97 | sys::path::remove_dots(config->pdbAltPath); |
1686 | 97 | } else { |
1687 | 13 | // Don't do this earlier, so that Config->OutputFile is ready. |
1688 | 13 | parsePDBAltPath(config->pdbAltPath); |
1689 | 13 | } |
1690 | 110 | } |
1691 | 618 | |
1692 | 618 | // Set default image base if /base is not given. |
1693 | 618 | if (config->imageBase == uint64_t(-1)) |
1694 | 616 | config->imageBase = getDefaultImageBase(); |
1695 | 618 | |
1696 | 618 | symtab->addSynthetic(mangle("__ImageBase"), nullptr); |
1697 | 618 | if (config->machine == I386) { |
1698 | 102 | symtab->addAbsolute("___safe_se_handler_table", 0); |
1699 | 102 | symtab->addAbsolute("___safe_se_handler_count", 0); |
1700 | 102 | } |
1701 | 618 | |
1702 | 618 | symtab->addAbsolute(mangle("__guard_fids_count"), 0); |
1703 | 618 | symtab->addAbsolute(mangle("__guard_fids_table"), 0); |
1704 | 618 | symtab->addAbsolute(mangle("__guard_flags"), 0); |
1705 | 618 | symtab->addAbsolute(mangle("__guard_iat_count"), 0); |
1706 | 618 | symtab->addAbsolute(mangle("__guard_iat_table"), 0); |
1707 | 618 | symtab->addAbsolute(mangle("__guard_longjmp_count"), 0); |
1708 | 618 | symtab->addAbsolute(mangle("__guard_longjmp_table"), 0); |
1709 | 618 | // Needed for MSVC 2017 15.5 CRT. |
1710 | 618 | symtab->addAbsolute(mangle("__enclave_config"), 0); |
1711 | 618 | |
1712 | 618 | if (config->mingw) { |
1713 | 47 | symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0); |
1714 | 47 | symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0); |
1715 | 47 | symtab->addAbsolute(mangle("__CTOR_LIST__"), 0); |
1716 | 47 | symtab->addAbsolute(mangle("__DTOR_LIST__"), 0); |
1717 | 47 | } |
1718 | 618 | |
1719 | 618 | // This code may add new undefined symbols to the link, which may enqueue more |
1720 | 618 | // symbol resolution tasks, so we need to continue executing tasks until we |
1721 | 618 | // converge. |
1722 | 625 | do { |
1723 | 625 | // Windows specific -- if entry point is not found, |
1724 | 625 | // search for its mangled names. |
1725 | 625 | if (config->entry) |
1726 | 585 | mangleMaybe(config->entry); |
1727 | 625 | |
1728 | 625 | // Windows specific -- Make sure we resolve all dllexported symbols. |
1729 | 625 | for (Export &e : config->exports) { |
1730 | 195 | if (!e.forwardTo.empty()) |
1731 | 2 | continue; |
1732 | 193 | e.sym = addUndefined(e.name); |
1733 | 193 | if (!e.directives) |
1734 | 77 | e.symbolName = mangleMaybe(e.sym); |
1735 | 193 | } |
1736 | 625 | |
1737 | 625 | // Add weak aliases. Weak aliases is a mechanism to give remaining |
1738 | 625 | // undefined symbols final chance to be resolved successfully. |
1739 | 625 | for (auto pair : config->alternateNames) { |
1740 | 10 | StringRef from = pair.first; |
1741 | 10 | StringRef to = pair.second; |
1742 | 10 | Symbol *sym = symtab->find(from); |
1743 | 10 | if (!sym) |
1744 | 2 | continue; |
1745 | 8 | if (auto *u = dyn_cast<Undefined>(sym)) |
1746 | 8 | if (!u->weakAlias) |
1747 | 8 | u->weakAlias = symtab->addUndefined(to); |
1748 | 8 | } |
1749 | 625 | |
1750 | 625 | // Windows specific -- if __load_config_used can be resolved, resolve it. |
1751 | 625 | if (symtab->findUnderscore("_load_config_used")) |
1752 | 25 | addUndefined(mangle("_load_config_used")); |
1753 | 625 | } while (run()); |
1754 | 618 | |
1755 | 618 | if (errorCount()) |
1756 | 4 | return; |
1757 | 614 | |
1758 | 614 | // Do LTO by compiling bitcode input files to a set of native COFF files then |
1759 | 614 | // link those files (unless -thinlto-index-only was given, in which case we |
1760 | 614 | // resolve symbols and write indices, but don't generate native code or link). |
1761 | 614 | symtab->addCombinedLTOObjects(); |
1762 | 614 | |
1763 | 614 | // If -thinlto-index-only is given, we should create only "index |
1764 | 614 | // files" and not object files. Index file creation is already done |
1765 | 614 | // in addCombinedLTOObject, so we are done if that's the case. |
1766 | 614 | if (config->thinLTOIndexOnly) |
1767 | 7 | return; |
1768 | 607 | |
1769 | 607 | // If we generated native object files from bitcode files, this resolves |
1770 | 607 | // references to the symbols we use from them. |
1771 | 607 | run(); |
1772 | 607 | |
1773 | 607 | if (args.hasArg(OPT_include_optional)) { |
1774 | 2 | // Handle /includeoptional |
1775 | 2 | for (auto *arg : args.filtered(OPT_include_optional)) |
1776 | 3 | if (dyn_cast_or_null<Lazy>(symtab->find(arg->getValue()))) |
1777 | 1 | addUndefined(arg->getValue()); |
1778 | 3 | while (run());1 |
1779 | 2 | } |
1780 | 607 | |
1781 | 607 | if (config->mingw) { |
1782 | 47 | // Load any further object files that might be needed for doing automatic |
1783 | 47 | // imports. |
1784 | 47 | // |
1785 | 47 | // For cases with no automatically imported symbols, this iterates once |
1786 | 47 | // over the symbol table and doesn't do anything. |
1787 | 47 | // |
1788 | 47 | // For the normal case with a few automatically imported symbols, this |
1789 | 47 | // should only need to be run once, since each new object file imported |
1790 | 47 | // is an import library and wouldn't add any new undefined references, |
1791 | 47 | // but there's nothing stopping the __imp_ symbols from coming from a |
1792 | 47 | // normal object file as well (although that won't be used for the |
1793 | 47 | // actual autoimport later on). If this pass adds new undefined references, |
1794 | 47 | // we won't iterate further to resolve them. |
1795 | 47 | symtab->loadMinGWAutomaticImports(); |
1796 | 47 | run(); |
1797 | 47 | } |
1798 | 607 | |
1799 | 607 | // Make sure we have resolved all symbols. |
1800 | 607 | symtab->reportRemainingUndefines(); |
1801 | 607 | if (errorCount()) |
1802 | 31 | return; |
1803 | 576 | |
1804 | 576 | if (config->mingw) { |
1805 | 46 | // In MinGW, all symbols are automatically exported if no symbols |
1806 | 46 | // are chosen to be exported. |
1807 | 46 | maybeExportMinGWSymbols(args); |
1808 | 46 | |
1809 | 46 | // Make sure the crtend.o object is the last object file. This object |
1810 | 46 | // file can contain terminating section chunks that need to be placed |
1811 | 46 | // last. GNU ld processes files and static libraries explicitly in the |
1812 | 46 | // order provided on the command line, while lld will pull in needed |
1813 | 46 | // files from static libraries only after the last object file on the |
1814 | 46 | // command line. |
1815 | 46 | for (auto i = ObjFile::instances.begin(), e = ObjFile::instances.end(); |
1816 | 110 | i != e; i++64 ) { |
1817 | 66 | ObjFile *file = *i; |
1818 | 66 | if (isCrtend(file->getName())) { |
1819 | 2 | ObjFile::instances.erase(i); |
1820 | 2 | ObjFile::instances.push_back(file); |
1821 | 2 | break; |
1822 | 2 | } |
1823 | 66 | } |
1824 | 46 | } |
1825 | 576 | |
1826 | 576 | // Windows specific -- when we are creating a .dll file, we also |
1827 | 576 | // need to create a .lib file. |
1828 | 576 | if (!config->exports.empty() || config->dll459 ) { |
1829 | 176 | fixupExports(); |
1830 | 176 | createImportLibrary(/*asLib=*/false); |
1831 | 176 | assignExportOrdinals(); |
1832 | 176 | } |
1833 | 576 | |
1834 | 576 | // Handle /output-def (MinGW specific). |
1835 | 576 | if (auto *arg = args.getLastArg(OPT_output_def)) |
1836 | 5 | writeDefFile(arg->getValue()); |
1837 | 576 | |
1838 | 576 | // Set extra alignment for .comm symbols |
1839 | 576 | for (auto pair : config->alignComm) { |
1840 | 2 | StringRef name = pair.first; |
1841 | 2 | uint32_t alignment = pair.second; |
1842 | 2 | |
1843 | 2 | Symbol *sym = symtab->find(name); |
1844 | 2 | if (!sym) { |
1845 | 0 | warn("/aligncomm symbol " + name + " not found"); |
1846 | 0 | continue; |
1847 | 0 | } |
1848 | 2 | |
1849 | 2 | // If the symbol isn't common, it must have been replaced with a regular |
1850 | 2 | // symbol, which will carry its own alignment. |
1851 | 2 | auto *dc = dyn_cast<DefinedCommon>(sym); |
1852 | 2 | if (!dc) |
1853 | 1 | continue; |
1854 | 1 | |
1855 | 1 | CommonChunk *c = dc->getChunk(); |
1856 | 1 | c->setAlignment(std::max(c->getAlignment(), alignment)); |
1857 | 1 | } |
1858 | 576 | |
1859 | 576 | // Windows specific -- Create a side-by-side manifest file. |
1860 | 576 | if (config->manifest == Configuration::SideBySide) |
1861 | 5 | createSideBySideManifest(); |
1862 | 576 | |
1863 | 576 | // Handle /order. We want to do this at this moment because we |
1864 | 576 | // need a complete list of comdat sections to warn on nonexistent |
1865 | 576 | // functions. |
1866 | 576 | if (auto *arg = args.getLastArg(OPT_order)) |
1867 | 10 | parseOrderFile(arg->getValue()); |
1868 | 576 | |
1869 | 576 | // Identify unreferenced COMDAT sections. |
1870 | 576 | if (config->doGC) |
1871 | 437 | markLive(symtab->getChunks()); |
1872 | 576 | |
1873 | 576 | // Needs to happen after the last call to addFile(). |
1874 | 576 | diagnoseMultipleResourceObjFiles(); |
1875 | 576 | |
1876 | 576 | // Identify identical COMDAT sections to merge them. |
1877 | 576 | if (config->doICF) { |
1878 | 436 | findKeepUniqueSections(); |
1879 | 436 | doICF(symtab->getChunks()); |
1880 | 436 | } |
1881 | 576 | |
1882 | 576 | // Write the result. |
1883 | 576 | writeResult(); |
1884 | 576 | |
1885 | 576 | // Stop early so we can print the results. |
1886 | 576 | Timer::root().stop(); |
1887 | 576 | if (config->showTiming) |
1888 | 0 | Timer::root().print(); |
1889 | 576 | } |
1890 | | |
1891 | | } // namespace coff |
1892 | | } // namespace lld |