clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name DarwinLdDriver.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/lld/lib/Driver -I /build/llvm-toolchain-snapshot-7~svn329677/tools/lld/lib/Driver -I /build/llvm-toolchain-snapshot-7~svn329677/tools/lld/include -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/lld/include -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn329677/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/lld/lib/Driver -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-04-11-031539-24776-1 -x c++ /build/llvm-toolchain-snapshot-7~svn329677/tools/lld/lib/Driver/DarwinLdDriver.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | #include "lld/Common/LLVM.h" |
17 | #include "lld/Core/ArchiveLibraryFile.h" |
18 | #include "lld/Core/Error.h" |
19 | #include "lld/Core/File.h" |
20 | #include "lld/Core/Instrumentation.h" |
21 | #include "lld/Core/LinkingContext.h" |
22 | #include "lld/Core/Node.h" |
23 | #include "lld/Core/PassManager.h" |
24 | #include "lld/Core/Resolver.h" |
25 | #include "lld/Core/SharedLibraryFile.h" |
26 | #include "lld/Core/Simple.h" |
27 | #include "lld/ReaderWriter/MachOLinkingContext.h" |
28 | #include "llvm/ADT/ArrayRef.h" |
29 | #include "llvm/ADT/Optional.h" |
30 | #include "llvm/ADT/STLExtras.h" |
31 | #include "llvm/ADT/SmallString.h" |
32 | #include "llvm/ADT/StringExtras.h" |
33 | #include "llvm/ADT/StringRef.h" |
34 | #include "llvm/ADT/Twine.h" |
35 | #include "llvm/BinaryFormat/MachO.h" |
36 | #include "llvm/Option/Arg.h" |
37 | #include "llvm/Option/ArgList.h" |
38 | #include "llvm/Option/OptTable.h" |
39 | #include "llvm/Option/Option.h" |
40 | #include "llvm/Support/Casting.h" |
41 | #include "llvm/Support/CommandLine.h" |
42 | #include "llvm/Support/Error.h" |
43 | #include "llvm/Support/ErrorOr.h" |
44 | #include "llvm/Support/Format.h" |
45 | #include "llvm/Support/MathExtras.h" |
46 | #include "llvm/Support/MemoryBuffer.h" |
47 | #include "llvm/Support/Path.h" |
48 | #include "llvm/Support/raw_ostream.h" |
49 | #include <algorithm> |
50 | #include <cstdint> |
51 | #include <memory> |
52 | #include <string> |
53 | #include <system_error> |
54 | #include <utility> |
55 | #include <vector> |
56 | |
57 | using namespace lld; |
58 | |
59 | namespace { |
60 | |
61 | |
62 | enum { |
63 | OPT_INVALID = 0, |
64 | #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ |
65 | HELP, META, VALUES) \ |
66 | OPT_##ID, |
67 | #include "DarwinLdOptions.inc" |
68 | #undef OPTION |
69 | }; |
70 | |
71 | |
72 | #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; |
73 | #include "DarwinLdOptions.inc" |
74 | #undef PREFIX |
75 | |
76 | |
77 | static const llvm::opt::OptTable::Info InfoTable[] = { |
78 | #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ |
79 | HELPTEXT, METAVAR, VALUES) \ |
80 | {PREFIX, NAME, HELPTEXT, \ |
81 | METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ |
82 | PARAM, FLAGS, OPT_##GROUP, \ |
83 | OPT_##ALIAS, ALIASARGS, VALUES}, |
84 | #include "DarwinLdOptions.inc" |
85 | #undef OPTION |
86 | }; |
87 | |
88 | |
89 | class DarwinLdOptTable : public llvm::opt::OptTable { |
90 | public: |
91 | DarwinLdOptTable() : OptTable(InfoTable) {} |
92 | }; |
93 | |
94 | static std::vector<std::unique_ptr<File>> |
95 | makeErrorFile(StringRef path, std::error_code ec) { |
96 | std::vector<std::unique_ptr<File>> result; |
97 | result.push_back(llvm::make_unique<ErrorFile>(path, ec)); |
98 | return result; |
99 | } |
100 | |
101 | static std::vector<std::unique_ptr<File>> |
102 | parseMemberFiles(std::unique_ptr<File> file) { |
103 | std::vector<std::unique_ptr<File>> members; |
104 | if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) { |
105 | if (std::error_code ec = archive->parseAllMembers(members)) |
106 | return makeErrorFile(file->path(), ec); |
107 | } else { |
108 | members.push_back(std::move(file)); |
109 | } |
110 | return members; |
111 | } |
112 | |
113 | std::vector<std::unique_ptr<File>> |
114 | loadFile(MachOLinkingContext &ctx, StringRef path, |
115 | raw_ostream &diag, bool wholeArchive, bool upwardDylib) { |
116 | if (ctx.logInputFiles()) |
117 | diag << path << "\n"; |
118 | |
119 | ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = ctx.getMemoryBuffer(path); |
120 | if (std::error_code ec = mbOrErr.getError()) |
121 | return makeErrorFile(path, ec); |
122 | ErrorOr<std::unique_ptr<File>> fileOrErr = |
123 | ctx.registry().loadFile(std::move(mbOrErr.get())); |
124 | if (std::error_code ec = fileOrErr.getError()) |
125 | return makeErrorFile(path, ec); |
126 | std::unique_ptr<File> &file = fileOrErr.get(); |
127 | |
128 | |
129 | if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(file.get())) { |
130 | if (std::error_code ec = shl->parse()) |
131 | return makeErrorFile(path, ec); |
132 | ctx.registerDylib(reinterpret_cast<mach_o::MachODylibFile *>(shl), |
133 | upwardDylib); |
134 | } |
135 | if (wholeArchive) |
136 | return parseMemberFiles(std::move(file)); |
137 | std::vector<std::unique_ptr<File>> files; |
138 | files.push_back(std::move(file)); |
139 | return files; |
140 | } |
141 | |
142 | } |
143 | |
144 | |
145 | |
146 | static std::string canonicalizePath(StringRef path) { |
147 | char sep = llvm::sys::path::get_separator().front(); |
148 | if (sep != '/') { |
149 | std::string fixedPath = path; |
150 | std::replace(fixedPath.begin(), fixedPath.end(), sep, '/'); |
151 | return fixedPath; |
152 | } else { |
153 | return path; |
154 | } |
155 | } |
156 | |
157 | static void addFile(StringRef path, MachOLinkingContext &ctx, |
158 | bool loadWholeArchive, |
159 | bool upwardDylib, raw_ostream &diag) { |
160 | std::vector<std::unique_ptr<File>> files = |
161 | loadFile(ctx, path, diag, loadWholeArchive, upwardDylib); |
162 | for (std::unique_ptr<File> &file : files) |
163 | ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file))); |
164 | } |
165 | |
166 | |
167 | |
168 | static std::error_code parseExportsList(StringRef exportFilePath, |
169 | MachOLinkingContext &ctx, |
170 | raw_ostream &diagnostics) { |
171 | |
172 | ErrorOr<std::unique_ptr<MemoryBuffer>> mb = |
173 | MemoryBuffer::getFileOrSTDIN(exportFilePath); |
174 | if (std::error_code ec = mb.getError()) |
175 | return ec; |
176 | ctx.addInputFileDependency(exportFilePath); |
177 | StringRef buffer = mb->get()->getBuffer(); |
178 | while (!buffer.empty()) { |
179 | |
180 | std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n'); |
181 | StringRef line = lineAndRest.first; |
182 | |
183 | std::pair<StringRef, StringRef> symAndComment = line.split('#'); |
184 | StringRef sym = symAndComment.first.trim(); |
185 | if (!sym.empty()) |
186 | ctx.addExportSymbol(sym); |
187 | buffer = lineAndRest.second; |
188 | } |
189 | return std::error_code(); |
190 | } |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | static std::error_code parseOrderFile(StringRef orderFilePath, |
200 | MachOLinkingContext &ctx, |
201 | raw_ostream &diagnostics) { |
202 | |
203 | ErrorOr<std::unique_ptr<MemoryBuffer>> mb = |
204 | MemoryBuffer::getFileOrSTDIN(orderFilePath); |
205 | if (std::error_code ec = mb.getError()) |
206 | return ec; |
207 | ctx.addInputFileDependency(orderFilePath); |
208 | StringRef buffer = mb->get()->getBuffer(); |
209 | while (!buffer.empty()) { |
210 | |
211 | std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n'); |
212 | StringRef line = lineAndRest.first; |
213 | buffer = lineAndRest.second; |
214 | |
215 | std::pair<StringRef, StringRef> symAndComment = line.split('#'); |
216 | if (symAndComment.first.empty()) |
217 | continue; |
218 | StringRef sym = symAndComment.first.trim(); |
219 | if (sym.empty()) |
220 | continue; |
221 | |
222 | StringRef prefix; |
223 | std::pair<StringRef, StringRef> prefixAndSym = sym.split(':'); |
224 | if (!prefixAndSym.second.empty()) { |
225 | sym = prefixAndSym.second; |
226 | prefix = prefixAndSym.first; |
227 | if (!prefix.endswith(".o") && !prefix.endswith(".o)")) { |
228 | |
229 | if (!ctx.archName().equals(prefix)) |
230 | continue; |
231 | prefix = ""; |
232 | } |
233 | } else |
234 | sym = prefixAndSym.first; |
235 | if (!sym.empty()) { |
236 | ctx.appendOrderedSymbol(sym, prefix); |
237 | |
238 | } |
239 | } |
240 | return std::error_code(); |
241 | } |
242 | |
243 | |
244 | |
245 | |
246 | |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | |
254 | static llvm::Error loadFileList(StringRef fileListPath, |
255 | MachOLinkingContext &ctx, bool forceLoad, |
256 | raw_ostream &diagnostics) { |
257 | |
258 | std::pair<StringRef, StringRef> opt = fileListPath.split(','); |
259 | StringRef filePath = opt.first; |
260 | StringRef dirName = opt.second; |
261 | ctx.addInputFileDependency(filePath); |
262 | |
263 | ErrorOr<std::unique_ptr<MemoryBuffer>> mb = |
264 | MemoryBuffer::getFileOrSTDIN(filePath); |
265 | if (std::error_code ec = mb.getError()) |
266 | return llvm::errorCodeToError(ec); |
267 | StringRef buffer = mb->get()->getBuffer(); |
268 | while (!buffer.empty()) { |
269 | |
270 | std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n'); |
271 | StringRef line = lineAndRest.first; |
272 | StringRef path; |
273 | if (!dirName.empty()) { |
274 | |
275 | SmallString<256> fullPath; |
276 | fullPath.assign(dirName); |
277 | llvm::sys::path::append(fullPath, Twine(line)); |
278 | path = ctx.copy(fullPath.str()); |
279 | } else { |
280 | |
281 | path = ctx.copy(line); |
282 | } |
283 | if (!ctx.pathExists(path)) { |
284 | return llvm::make_error<GenericError>(Twine("File not found '") |
285 | + path |
286 | + "'"); |
287 | } |
288 | if (ctx.testingFileUsage()) { |
289 | diagnostics << "Found filelist entry " << canonicalizePath(path) << '\n'; |
290 | } |
291 | addFile(path, ctx, forceLoad, false, diagnostics); |
292 | buffer = lineAndRest.second; |
293 | } |
294 | return llvm::Error::success(); |
295 | } |
296 | |
297 | |
298 | static bool parseNumberBase16(StringRef numStr, uint64_t &baseAddress) { |
299 | if (numStr.startswith_lower("0x")) |
300 | numStr = numStr.drop_front(2); |
301 | return numStr.getAsInteger(16, baseAddress); |
302 | } |
303 | |
304 | static void parseLLVMOptions(const LinkingContext &ctx) { |
305 | |
306 | if (!ctx.llvmOptions().empty()) { |
307 | unsigned numArgs = ctx.llvmOptions().size(); |
308 | auto **args = new const char *[numArgs + 2]; |
309 | args[0] = "lld (LLVM option parsing)"; |
310 | for (unsigned i = 0; i != numArgs; ++i) |
311 | args[i + 1] = ctx.llvmOptions()[i]; |
312 | args[numArgs + 1] = nullptr; |
313 | llvm::cl::ParseCommandLineOptions(numArgs + 1, args); |
314 | } |
315 | } |
316 | |
317 | namespace lld { |
318 | namespace mach_o { |
319 | |
320 | bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx, |
321 | raw_ostream &diagnostics) { |
322 | |
323 | DarwinLdOptTable table; |
324 | unsigned missingIndex; |
325 | unsigned missingCount; |
326 | llvm::opt::InputArgList parsedArgs = |
327 | table.ParseArgs(args.slice(1), missingIndex, missingCount); |
328 | if (missingCount) { |
| 1 | Assuming 'missingCount' is 0 | |
|
| |
329 | diagnostics << "error: missing arg value for '" |
330 | << parsedArgs.getArgString(missingIndex) << "' expected " |
331 | << missingCount << " argument(s).\n"; |
332 | return false; |
333 | } |
334 | |
335 | for (auto unknownArg : parsedArgs.filtered(OPT_UNKNOWN)) { |
336 | diagnostics << "warning: ignoring unknown argument: " |
337 | << unknownArg->getAsString(parsedArgs) << "\n"; |
338 | } |
339 | |
340 | |
341 | llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE; |
342 | bool isStaticExecutable = false; |
343 | if (llvm::opt::Arg *kind = parsedArgs.getLastArg( |
| |
| |
344 | OPT_dylib, OPT_relocatable, OPT_bundle, OPT_static, OPT_preload)) { |
345 | switch (kind->getOption().getID()) { |
346 | case OPT_dylib: |
347 | fileType = llvm::MachO::MH_DYLIB; |
348 | break; |
349 | case OPT_relocatable: |
350 | fileType = llvm::MachO::MH_OBJECT; |
351 | break; |
352 | case OPT_bundle: |
353 | fileType = llvm::MachO::MH_BUNDLE; |
354 | break; |
355 | case OPT_static: |
356 | fileType = llvm::MachO::MH_EXECUTE; |
357 | isStaticExecutable = true; |
358 | break; |
359 | case OPT_preload: |
360 | fileType = llvm::MachO::MH_PRELOAD; |
361 | break; |
362 | } |
363 | } |
364 | |
365 | |
366 | MachOLinkingContext::Arch arch = MachOLinkingContext::arch_unknown; |
367 | if (llvm::opt::Arg *archStr = parsedArgs.getLastArg(OPT_arch)) { |
| 5 | | Assuming 'archStr' is null | |
|
| |
368 | arch = MachOLinkingContext::archFromName(archStr->getValue()); |
369 | if (arch == MachOLinkingContext::arch_unknown) { |
370 | diagnostics << "error: unknown arch named '" << archStr->getValue() |
371 | << "'\n"; |
372 | return false; |
373 | } |
374 | } |
375 | |
376 | if (arch == MachOLinkingContext::arch_unknown) { |
| |
377 | for (auto &inFile : parsedArgs.filtered(OPT_INPUT)) { |
378 | |
379 | |
380 | if (MachOLinkingContext::isThinObjectFile(inFile->getValue(), arch)) |
| 8 | | Assuming the condition is true | |
|
| |
381 | break; |
| 10 | | Execution continues on line 383 | |
|
382 | } |
383 | if (arch == MachOLinkingContext::arch_unknown && |
| 11 | | Assuming 'arch' is not equal to arch_unknown | |
|
384 | !parsedArgs.getLastArg(OPT_test_file_usage)) { |
385 | |
386 | if (parsedArgs.size() == 0) |
387 | table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false); |
388 | else |
389 | diagnostics << "error: -arch not specified and could not be inferred\n"; |
390 | return false; |
391 | } |
392 | } |
393 | |
394 | |
395 | MachOLinkingContext::OS os = MachOLinkingContext::OS::unknown; |
396 | uint32_t minOSVersion = 0; |
397 | if (llvm::opt::Arg *minOS = |
| 12 | | Assuming 'minOS' is null | |
|
| |
398 | parsedArgs.getLastArg(OPT_macosx_version_min, OPT_ios_version_min, |
399 | OPT_ios_simulator_version_min)) { |
400 | switch (minOS->getOption().getID()) { |
401 | case OPT_macosx_version_min: |
402 | os = MachOLinkingContext::OS::macOSX; |
403 | if (MachOLinkingContext::parsePackedVersion(minOS->getValue(), |
404 | minOSVersion)) { |
405 | diagnostics << "error: malformed macosx_version_min value\n"; |
406 | return false; |
407 | } |
408 | break; |
409 | case OPT_ios_version_min: |
410 | os = MachOLinkingContext::OS::iOS; |
411 | if (MachOLinkingContext::parsePackedVersion(minOS->getValue(), |
412 | minOSVersion)) { |
413 | diagnostics << "error: malformed ios_version_min value\n"; |
414 | return false; |
415 | } |
416 | break; |
417 | case OPT_ios_simulator_version_min: |
418 | os = MachOLinkingContext::OS::iOS_simulator; |
419 | if (MachOLinkingContext::parsePackedVersion(minOS->getValue(), |
420 | minOSVersion)) { |
421 | diagnostics << "error: malformed ios_simulator_version_min value\n"; |
422 | return false; |
423 | } |
424 | break; |
425 | } |
426 | } else { |
427 | |
428 | } |
429 | |
430 | |
431 | |
432 | |
433 | |
434 | |
435 | bool exportDynamicSymbols = parsedArgs.hasArg(OPT_export_dynamic); |
436 | |
437 | |
438 | |
439 | ctx.configure(fileType, arch, os, minOSVersion, exportDynamicSymbols); |
440 | |
441 | |
442 | if (llvm::opt::Arg *entry = parsedArgs.getLastArg(OPT_entry)) |
| 14 | | Assuming 'entry' is null | |
|
| |
443 | ctx.setEntrySymbolName(entry->getValue()); |
444 | |
445 | |
446 | if (llvm::opt::Arg *outpath = parsedArgs.getLastArg(OPT_output)) |
| 16 | | Assuming 'outpath' is null | |
|
| |
447 | ctx.setOutputPath(outpath->getValue()); |
448 | else |
449 | ctx.setOutputPath("a.out"); |
450 | |
451 | |
452 | if (llvm::opt::Arg *imageBase = parsedArgs.getLastArg(OPT_image_base)) { |
| 18 | | Assuming 'imageBase' is null | |
|
| |
453 | uint64_t baseAddress; |
454 | if (parseNumberBase16(imageBase->getValue(), baseAddress)) { |
455 | diagnostics << "error: image_base expects a hex number\n"; |
456 | return false; |
457 | } else if (baseAddress < ctx.pageZeroSize()) { |
458 | diagnostics << "error: image_base overlaps with __PAGEZERO\n"; |
459 | return false; |
460 | } else if (baseAddress % ctx.pageSize()) { |
461 | diagnostics << "error: image_base must be a multiple of page size (" |
462 | << "0x" << llvm::utohexstr(ctx.pageSize()) << ")\n"; |
463 | return false; |
464 | } |
465 | |
466 | ctx.setBaseAddress(baseAddress); |
467 | } |
468 | |
469 | |
470 | if (parsedArgs.getLastArg(OPT_dead_strip)) |
| 20 | | Assuming the condition is false | |
|
| |
471 | ctx.setDeadStripping(true); |
472 | |
473 | bool globalWholeArchive = false; |
474 | |
475 | if (parsedArgs.getLastArg(OPT_all_load)) |
| 22 | | Assuming the condition is false | |
|
| |
476 | globalWholeArchive = true; |
477 | |
478 | |
479 | if (llvm::opt::Arg *installName = parsedArgs.getLastArg(OPT_install_name)) |
| 24 | | Assuming 'installName' is null | |
|
| |
480 | ctx.setInstallName(installName->getValue()); |
481 | else |
482 | ctx.setInstallName(ctx.outputPath()); |
483 | |
484 | |
485 | if (parsedArgs.getLastArg(OPT_mark_dead_strippable_dylib)) |
| 26 | | Assuming the condition is false | |
|
| |
486 | ctx.setDeadStrippableDylib(true); |
487 | |
488 | |
489 | if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_compatibility_version)) { |
| 28 | | Assuming 'vers' is null | |
|
| |
490 | if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) { |
491 | diagnostics |
492 | << "error: -compatibility_version can only be used with -dylib\n"; |
493 | return false; |
494 | } |
495 | uint32_t parsedVers; |
496 | if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) { |
497 | diagnostics << "error: -compatibility_version value is malformed\n"; |
498 | return false; |
499 | } |
500 | ctx.setCompatibilityVersion(parsedVers); |
501 | } |
502 | |
503 | if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_current_version)) { |
| 30 | | Assuming 'vers' is null | |
|
| |
504 | if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) { |
505 | diagnostics << "-current_version can only be used with -dylib\n"; |
506 | return false; |
507 | } |
508 | uint32_t parsedVers; |
509 | if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) { |
510 | diagnostics << "error: -current_version value is malformed\n"; |
511 | return false; |
512 | } |
513 | ctx.setCurrentVersion(parsedVers); |
514 | } |
515 | |
516 | |
517 | if (llvm::opt::Arg *loader = parsedArgs.getLastArg(OPT_bundle_loader)) |
| 32 | | Assuming 'loader' is null | |
|
| |
518 | ctx.setBundleLoader(loader->getValue()); |
519 | |
520 | |
521 | for (auto &alignArg : parsedArgs.filtered(OPT_sectalign)) { |
522 | const char* segName = alignArg->getValue(0); |
523 | const char* sectName = alignArg->getValue(1); |
524 | const char* alignStr = alignArg->getValue(2); |
525 | if ((alignStr[0] == '0') && (alignStr[1] == 'x')) |
| 34 | | Assuming the condition is false | |
|
526 | alignStr += 2; |
527 | unsigned long long alignValue; |
528 | if (llvm::getAsUnsignedInteger(alignStr, 16, alignValue)) { |
| 35 | | Assuming the condition is false | |
|
| |
529 | diagnostics << "error: -sectalign alignment value '" |
530 | << alignStr << "' not a valid number\n"; |
531 | return false; |
532 | } |
533 | uint16_t align = 1 << llvm::countTrailingZeros(alignValue); |
| 37 | | The result of the left shift is undefined due to shifting by '64', which is greater or equal to the width of type 'int' |
|
534 | if (!llvm::isPowerOf2_64(alignValue)) { |
535 | diagnostics << "warning: alignment for '-sectalign " |
536 | << segName << " " << sectName |
537 | << llvm::format(" 0x%llX", alignValue) |
538 | << "' is not a power of two, using " |
539 | << llvm::format("0x%08X", align) << "\n"; |
540 | } |
541 | ctx.addSectionAlignment(segName, sectName, align); |
542 | } |
543 | |
544 | |
545 | for (auto &llvmArg : parsedArgs.filtered(OPT_mllvm)) { |
546 | ctx.appendLLVMOption(llvmArg->getValue()); |
547 | } |
548 | |
549 | |
550 | if (parsedArgs.getLastArg(OPT_print_atoms)) |
551 | ctx.setPrintAtoms(); |
552 | |
553 | |
554 | if (parsedArgs.getLastArg(OPT_t)) |
555 | ctx.setLogInputFiles(true); |
556 | |
557 | |
558 | if (parsedArgs.getLastArg(OPT_demangle)) |
559 | ctx.setDemangleSymbols(true); |
560 | |
561 | |
562 | if (parsedArgs.getLastArg(OPT_keep_private_externs)) { |
563 | ctx.setKeepPrivateExterns(true); |
564 | if (ctx.outputMachOType() != llvm::MachO::MH_OBJECT) |
565 | diagnostics << "warning: -keep_private_externs only used in -r mode\n"; |
566 | } |
567 | |
568 | |
569 | if (llvm::opt::Arg *depInfo = parsedArgs.getLastArg(OPT_dependency_info)) { |
570 | if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue())) { |
571 | diagnostics << "warning: " << ec.message() |
572 | << ", processing '-dependency_info " |
573 | << depInfo->getValue() |
574 | << "'\n"; |
575 | } |
576 | } |
577 | |
578 | |
579 | |
580 | |
581 | |
582 | if (parsedArgs.getLastArg(OPT_test_file_usage)) { |
583 | ctx.setTestingFileUsage(); |
584 | |
585 | |
586 | ctx.setDoNothing(true); |
587 | |
588 | |
589 | for (auto existingPath : parsedArgs.filtered(OPT_path_exists)) { |
590 | ctx.addExistingPathForDebug(existingPath->getValue()); |
591 | } |
592 | } |
593 | |
594 | |
595 | if (!ctx.doNothing()) { |
596 | ctx.registry().addSupportMachOObjects(ctx); |
597 | ctx.registry().addSupportArchives(ctx.logInputFiles()); |
598 | ctx.registry().addSupportYamlFiles(); |
599 | } |
600 | |
601 | |
602 | |
603 | |
604 | |
605 | |
606 | |
607 | |
608 | |
609 | |
610 | |
611 | std::vector<StringRef> sysLibRoots; |
612 | for (auto syslibRoot : parsedArgs.filtered(OPT_syslibroot)) { |
613 | sysLibRoots.push_back(syslibRoot->getValue()); |
614 | } |
615 | if (!sysLibRoots.empty()) { |
616 | |
617 | if (sysLibRoots.back() != "/") |
618 | ctx.setSysLibRoots(sysLibRoots); |
619 | } |
620 | |
621 | |
622 | |
623 | for (auto libPath : parsedArgs.filtered(OPT_L)) { |
624 | ctx.addModifiedSearchDir(libPath->getValue()); |
625 | } |
626 | |
627 | |
628 | for (auto fwPath : parsedArgs.filtered(OPT_F)) { |
629 | ctx.addFrameworkSearchDir(fwPath->getValue()); |
630 | } |
631 | |
632 | |
633 | if (!parsedArgs.hasArg(OPT_Z)) { |
634 | ctx.addModifiedSearchDir("/usr/lib", true); |
635 | ctx.addModifiedSearchDir("/usr/local/lib", true); |
636 | ctx.addFrameworkSearchDir("/Library/Frameworks", true); |
637 | ctx.addFrameworkSearchDir("/System/Library/Frameworks", true); |
638 | } |
639 | |
640 | |
641 | |
642 | if (parsedArgs.getLastArg(OPT_v)) { |
643 | diagnostics << "Library search paths:\n"; |
644 | for (auto path : ctx.searchDirs()) { |
645 | diagnostics << " " << path << '\n'; |
646 | } |
647 | diagnostics << "Framework search paths:\n"; |
648 | for (auto path : ctx.frameworkDirs()) { |
649 | diagnostics << " " << path << '\n'; |
650 | } |
651 | } |
652 | |
653 | |
654 | for (auto expFile : parsedArgs.filtered(OPT_exported_symbols_list)) { |
655 | if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) { |
656 | diagnostics << "error: -exported_symbols_list cannot be combined " |
657 | << "with -unexported_symbol[s_list]\n"; |
658 | return false; |
659 | } |
660 | ctx.setExportMode(MachOLinkingContext::ExportMode::whiteList); |
661 | if (std::error_code ec = parseExportsList(expFile->getValue(), ctx, |
662 | diagnostics)) { |
663 | diagnostics << "error: " << ec.message() |
664 | << ", processing '-exported_symbols_list " |
665 | << expFile->getValue() |
666 | << "'\n"; |
667 | return false; |
668 | } |
669 | } |
670 | |
671 | |
672 | for (auto symbol : parsedArgs.filtered(OPT_exported_symbol)) { |
673 | if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) { |
674 | diagnostics << "error: -exported_symbol cannot be combined " |
675 | << "with -unexported_symbol[s_list]\n"; |
676 | return false; |
677 | } |
678 | ctx.setExportMode(MachOLinkingContext::ExportMode::whiteList); |
679 | ctx.addExportSymbol(symbol->getValue()); |
680 | } |
681 | |
682 | |
683 | for (auto expFile : parsedArgs.filtered(OPT_unexported_symbols_list)) { |
684 | if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) { |
685 | diagnostics << "error: -unexported_symbols_list cannot be combined " |
686 | << "with -exported_symbol[s_list]\n"; |
687 | return false; |
688 | } |
689 | ctx.setExportMode(MachOLinkingContext::ExportMode::blackList); |
690 | if (std::error_code ec = parseExportsList(expFile->getValue(), ctx, |
691 | diagnostics)) { |
692 | diagnostics << "error: " << ec.message() |
693 | << ", processing '-unexported_symbols_list " |
694 | << expFile->getValue() |
695 | << "'\n"; |
696 | return false; |
697 | } |
698 | } |
699 | |
700 | |
701 | for (auto symbol : parsedArgs.filtered(OPT_unexported_symbol)) { |
702 | if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) { |
703 | diagnostics << "error: -unexported_symbol cannot be combined " |
704 | << "with -exported_symbol[s_list]\n"; |
705 | return false; |
706 | } |
707 | ctx.setExportMode(MachOLinkingContext::ExportMode::blackList); |
708 | ctx.addExportSymbol(symbol->getValue()); |
709 | } |
710 | |
711 | |
712 | if (llvm::opt::Arg *mod = |
713 | parsedArgs.getLastArg(OPT_multi_module, OPT_single_module)) { |
714 | if (mod->getOption().getID() == OPT_multi_module) { |
715 | diagnostics << "warning: -multi_module is obsolete and being ignored\n"; |
716 | } |
717 | else { |
718 | if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) { |
719 | diagnostics << "warning: -single_module being ignored. " |
720 | "It is only for use when producing a dylib\n"; |
721 | } |
722 | } |
723 | } |
724 | |
725 | |
726 | if (parsedArgs.getLastArg(OPT_objc_gc_compaction)) { |
727 | diagnostics << "error: -objc_gc_compaction is not supported\n"; |
728 | return false; |
729 | } |
730 | |
731 | if (parsedArgs.getLastArg(OPT_objc_gc)) { |
732 | diagnostics << "error: -objc_gc is not supported\n"; |
733 | return false; |
734 | } |
735 | |
736 | if (parsedArgs.getLastArg(OPT_objc_gc_only)) { |
737 | diagnostics << "error: -objc_gc_only is not supported\n"; |
738 | return false; |
739 | } |
740 | |
741 | |
742 | if (llvm::opt::Arg *pie = parsedArgs.getLastArg(OPT_pie, OPT_no_pie)) { |
743 | switch (ctx.outputMachOType()) { |
744 | case llvm::MachO::MH_EXECUTE: |
745 | switch (ctx.os()) { |
746 | case MachOLinkingContext::OS::macOSX: |
747 | if ((minOSVersion < 0x000A0500) && |
748 | (pie->getOption().getID() == OPT_pie)) { |
749 | diagnostics << "-pie can only be used when targeting " |
750 | "Mac OS X 10.5 or later\n"; |
751 | return false; |
752 | } |
753 | break; |
754 | case MachOLinkingContext::OS::iOS: |
755 | if ((minOSVersion < 0x00040200) && |
756 | (pie->getOption().getID() == OPT_pie)) { |
757 | diagnostics << "-pie can only be used when targeting " |
758 | "iOS 4.2 or later\n"; |
759 | return false; |
760 | } |
761 | break; |
762 | case MachOLinkingContext::OS::iOS_simulator: |
763 | if (pie->getOption().getID() == OPT_no_pie) { |
764 | diagnostics << "iOS simulator programs must be built PIE\n"; |
765 | return false; |
766 | } |
767 | break; |
768 | case MachOLinkingContext::OS::unknown: |
769 | break; |
770 | } |
771 | ctx.setPIE(pie->getOption().getID() == OPT_pie); |
772 | break; |
773 | case llvm::MachO::MH_PRELOAD: |
774 | break; |
775 | case llvm::MachO::MH_DYLIB: |
776 | case llvm::MachO::MH_BUNDLE: |
777 | diagnostics << "warning: " << pie->getSpelling() << " being ignored. " |
778 | << "It is only used when linking main executables\n"; |
779 | break; |
780 | default: |
781 | diagnostics << pie->getSpelling() |
782 | << " can only used when linking main executables\n"; |
783 | return false; |
784 | } |
785 | } |
786 | |
787 | |
788 | { |
789 | bool flagOn = false; |
790 | bool flagOff = false; |
791 | if (auto *arg = parsedArgs.getLastArg(OPT_version_load_command, |
792 | OPT_no_version_load_command)) { |
793 | flagOn = arg->getOption().getID() == OPT_version_load_command; |
794 | flagOff = arg->getOption().getID() == OPT_no_version_load_command; |
795 | } |
796 | |
797 | |
798 | |
799 | switch (ctx.outputMachOType()) { |
800 | case llvm::MachO::MH_OBJECT: |
801 | ctx.setGenerateVersionLoadCommand(false); |
802 | break; |
803 | case llvm::MachO::MH_EXECUTE: |
804 | |
805 | |
806 | if (isStaticExecutable) { |
807 | if (flagOn) |
808 | ctx.setGenerateVersionLoadCommand(true); |
809 | } else { |
810 | if (!flagOff) |
811 | ctx.setGenerateVersionLoadCommand(true); |
812 | } |
813 | break; |
814 | case llvm::MachO::MH_PRELOAD: |
815 | case llvm::MachO::MH_KEXT_BUNDLE: |
816 | if (flagOn) |
817 | ctx.setGenerateVersionLoadCommand(true); |
818 | break; |
819 | case llvm::MachO::MH_DYLINKER: |
820 | case llvm::MachO::MH_DYLIB: |
821 | case llvm::MachO::MH_BUNDLE: |
822 | if (!flagOff) |
823 | ctx.setGenerateVersionLoadCommand(true); |
824 | break; |
825 | case llvm::MachO::MH_FVMLIB: |
826 | case llvm::MachO::MH_DYLDLINK: |
827 | case llvm::MachO::MH_DYLIB_STUB: |
828 | case llvm::MachO::MH_DSYM: |
829 | |
830 | |
831 | break; |
832 | } |
833 | } |
834 | |
835 | |
836 | { |
837 | bool flagOn = false; |
838 | bool flagOff = false; |
839 | if (auto *arg = parsedArgs.getLastArg(OPT_function_starts, |
840 | OPT_no_function_starts)) { |
841 | flagOn = arg->getOption().getID() == OPT_function_starts; |
842 | flagOff = arg->getOption().getID() == OPT_no_function_starts; |
843 | } |
844 | |
845 | |
846 | |
847 | switch (ctx.outputMachOType()) { |
848 | case llvm::MachO::MH_OBJECT: |
849 | ctx.setGenerateFunctionStartsLoadCommand(false); |
850 | break; |
851 | case llvm::MachO::MH_EXECUTE: |
852 | |
853 | |
854 | if (isStaticExecutable) { |
855 | if (flagOn) |
856 | ctx.setGenerateFunctionStartsLoadCommand(true); |
857 | } else { |
858 | if (!flagOff) |
859 | ctx.setGenerateFunctionStartsLoadCommand(true); |
860 | } |
861 | break; |
862 | case llvm::MachO::MH_PRELOAD: |
863 | case llvm::MachO::MH_KEXT_BUNDLE: |
864 | if (flagOn) |
865 | ctx.setGenerateFunctionStartsLoadCommand(true); |
866 | break; |
867 | case llvm::MachO::MH_DYLINKER: |
868 | case llvm::MachO::MH_DYLIB: |
869 | case llvm::MachO::MH_BUNDLE: |
870 | if (!flagOff) |
871 | ctx.setGenerateFunctionStartsLoadCommand(true); |
872 | break; |
873 | case llvm::MachO::MH_FVMLIB: |
874 | case llvm::MachO::MH_DYLDLINK: |
875 | case llvm::MachO::MH_DYLIB_STUB: |
876 | case llvm::MachO::MH_DSYM: |
877 | |
878 | |
879 | break; |
880 | } |
881 | } |
882 | |
883 | |
884 | { |
885 | bool flagOn = false; |
886 | bool flagOff = false; |
887 | if (auto *arg = parsedArgs.getLastArg(OPT_data_in_code_info, |
888 | OPT_no_data_in_code_info)) { |
889 | flagOn = arg->getOption().getID() == OPT_data_in_code_info; |
890 | flagOff = arg->getOption().getID() == OPT_no_data_in_code_info; |
891 | } |
892 | |
893 | |
894 | |
895 | switch (ctx.outputMachOType()) { |
896 | case llvm::MachO::MH_OBJECT: |
897 | if (!flagOff) |
898 | ctx.setGenerateDataInCodeLoadCommand(true); |
899 | break; |
900 | case llvm::MachO::MH_EXECUTE: |
901 | |
902 | |
903 | if (isStaticExecutable) { |
904 | if (flagOn) |
905 | ctx.setGenerateDataInCodeLoadCommand(true); |
906 | } else { |
907 | if (!flagOff) |
908 | ctx.setGenerateDataInCodeLoadCommand(true); |
909 | } |
910 | break; |
911 | case llvm::MachO::MH_PRELOAD: |
912 | case llvm::MachO::MH_KEXT_BUNDLE: |
913 | if (flagOn) |
914 | ctx.setGenerateDataInCodeLoadCommand(true); |
915 | break; |
916 | case llvm::MachO::MH_DYLINKER: |
917 | case llvm::MachO::MH_DYLIB: |
918 | case llvm::MachO::MH_BUNDLE: |
919 | if (!flagOff) |
920 | ctx.setGenerateDataInCodeLoadCommand(true); |
921 | break; |
922 | case llvm::MachO::MH_FVMLIB: |
923 | case llvm::MachO::MH_DYLDLINK: |
924 | case llvm::MachO::MH_DYLIB_STUB: |
925 | case llvm::MachO::MH_DSYM: |
926 | |
927 | |
928 | break; |
929 | } |
930 | } |
931 | |
932 | |
933 | if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_sdk_version)) { |
934 | uint32_t sdkVersion = 0; |
935 | if (MachOLinkingContext::parsePackedVersion(arg->getValue(), |
936 | sdkVersion)) { |
937 | diagnostics << "error: malformed sdkVersion value\n"; |
938 | return false; |
939 | } |
940 | ctx.setSdkVersion(sdkVersion); |
941 | } else if (ctx.generateVersionLoadCommand()) { |
942 | |
943 | |
944 | |
945 | |
946 | diagnostics << "warning: -sdk_version is required when emitting " |
947 | "min version load command. " |
948 | "Setting sdk version to match provided min version\n"; |
949 | ctx.setSdkVersion(ctx.osMinVersion()); |
950 | } |
951 | |
952 | |
953 | if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_source_version)) { |
954 | uint64_t version = 0; |
955 | if (MachOLinkingContext::parsePackedVersion(arg->getValue(), |
956 | version)) { |
957 | diagnostics << "error: malformed source_version value\n"; |
958 | return false; |
959 | } |
960 | ctx.setSourceVersion(version); |
961 | } |
962 | |
963 | |
964 | if (llvm::opt::Arg *stackSize = parsedArgs.getLastArg(OPT_stack_size)) { |
965 | uint64_t stackSizeVal; |
966 | if (parseNumberBase16(stackSize->getValue(), stackSizeVal)) { |
967 | diagnostics << "error: stack_size expects a hex number\n"; |
968 | return false; |
969 | } |
970 | if ((stackSizeVal % ctx.pageSize()) != 0) { |
971 | diagnostics << "error: stack_size must be a multiple of page size (" |
972 | << "0x" << llvm::utohexstr(ctx.pageSize()) << ")\n"; |
973 | return false; |
974 | } |
975 | |
976 | ctx.setStackSize(stackSizeVal); |
977 | } |
978 | |
979 | |
980 | if (parsedArgs.hasArg(OPT_S)) |
981 | ctx.setDebugInfoMode(MachOLinkingContext::DebugInfoMode::noDebugMap); |
982 | |
983 | |
984 | for (auto orderFile : parsedArgs.filtered(OPT_order_file)) { |
985 | if (std::error_code ec = parseOrderFile(orderFile->getValue(), ctx, |
986 | diagnostics)) { |
987 | diagnostics << "error: " << ec.message() |
988 | << ", processing '-order_file " |
989 | << orderFile->getValue() |
990 | << "'\n"; |
991 | return false; |
992 | } |
993 | } |
994 | |
995 | |
996 | if (llvm::opt::Arg *ns = |
997 | parsedArgs.getLastArg(OPT_flat_namespace, OPT_twolevel_namespace)) { |
998 | if (ns->getOption().getID() == OPT_flat_namespace) |
999 | ctx.setUseFlatNamespace(true); |
1000 | } |
1001 | |
1002 | |
1003 | if (llvm::opt::Arg *undef = parsedArgs.getLastArg(OPT_undefined)) { |
1004 | MachOLinkingContext::UndefinedMode UndefMode; |
1005 | if (StringRef(undef->getValue()).equals("error")) |
1006 | UndefMode = MachOLinkingContext::UndefinedMode::error; |
1007 | else if (StringRef(undef->getValue()).equals("warning")) |
1008 | UndefMode = MachOLinkingContext::UndefinedMode::warning; |
1009 | else if (StringRef(undef->getValue()).equals("suppress")) |
1010 | UndefMode = MachOLinkingContext::UndefinedMode::suppress; |
1011 | else if (StringRef(undef->getValue()).equals("dynamic_lookup")) |
1012 | UndefMode = MachOLinkingContext::UndefinedMode::dynamicLookup; |
1013 | else { |
1014 | diagnostics << "error: invalid option to -undefined " |
1015 | "[ warning | error | suppress | dynamic_lookup ]\n"; |
1016 | return false; |
1017 | } |
1018 | |
1019 | if (ctx.useFlatNamespace()) { |
1020 | |
1021 | |
1022 | if (UndefMode != MachOLinkingContext::UndefinedMode::error) |
1023 | UndefMode = MachOLinkingContext::UndefinedMode::suppress; |
1024 | } else { |
1025 | |
1026 | |
1027 | if (UndefMode == MachOLinkingContext::UndefinedMode::warning || |
1028 | UndefMode == MachOLinkingContext::UndefinedMode::suppress) { |
1029 | diagnostics << "error: can't use -undefined warning or suppress with " |
1030 | "-twolevel_namespace\n"; |
1031 | return false; |
1032 | } |
1033 | } |
1034 | |
1035 | ctx.setUndefinedMode(UndefMode); |
1036 | } |
1037 | |
1038 | |
1039 | if (parsedArgs.getLastArg(OPT_no_objc_category_merging)) |
1040 | ctx.setMergeObjCCategories(false); |
1041 | |
1042 | |
1043 | if (parsedArgs.hasArg(OPT_rpath)) { |
1044 | switch (ctx.outputMachOType()) { |
1045 | case llvm::MachO::MH_EXECUTE: |
1046 | case llvm::MachO::MH_DYLIB: |
1047 | case llvm::MachO::MH_BUNDLE: |
1048 | if (!ctx.minOS("10.5", "2.0")) { |
1049 | if (ctx.os() == MachOLinkingContext::OS::macOSX) { |
1050 | diagnostics << "error: -rpath can only be used when targeting " |
1051 | "OS X 10.5 or later\n"; |
1052 | } else { |
1053 | diagnostics << "error: -rpath can only be used when targeting " |
1054 | "iOS 2.0 or later\n"; |
1055 | } |
1056 | return false; |
1057 | } |
1058 | break; |
1059 | default: |
1060 | diagnostics << "error: -rpath can only be used when creating " |
1061 | "a dynamic final linked image\n"; |
1062 | return false; |
1063 | } |
1064 | |
1065 | for (auto rPath : parsedArgs.filtered(OPT_rpath)) { |
1066 | ctx.addRpath(rPath->getValue()); |
1067 | } |
1068 | } |
1069 | |
1070 | |
1071 | |
1072 | parseLLVMOptions(ctx); |
1073 | |
1074 | |
1075 | for (auto &arg : parsedArgs) { |
1076 | bool upward; |
1077 | llvm::Optional<StringRef> resolvedPath; |
1078 | switch (arg->getOption().getID()) { |
1079 | default: |
1080 | continue; |
1081 | case OPT_INPUT: |
1082 | addFile(arg->getValue(), ctx, globalWholeArchive, false, diagnostics); |
1083 | break; |
1084 | case OPT_upward_library: |
1085 | addFile(arg->getValue(), ctx, false, true, diagnostics); |
1086 | break; |
1087 | case OPT_force_load: |
1088 | addFile(arg->getValue(), ctx, true, false, diagnostics); |
1089 | break; |
1090 | case OPT_l: |
1091 | case OPT_upward_l: |
1092 | upward = (arg->getOption().getID() == OPT_upward_l); |
1093 | resolvedPath = ctx.searchLibrary(arg->getValue()); |
1094 | if (!resolvedPath) { |
1095 | diagnostics << "Unable to find library for " << arg->getSpelling() |
1096 | << arg->getValue() << "\n"; |
1097 | return false; |
1098 | } else if (ctx.testingFileUsage()) { |
1099 | diagnostics << "Found " << (upward ? "upward " : " ") << "library " |
1100 | << canonicalizePath(resolvedPath.getValue()) << '\n'; |
1101 | } |
1102 | addFile(resolvedPath.getValue(), ctx, globalWholeArchive, |
1103 | upward, diagnostics); |
1104 | break; |
1105 | case OPT_framework: |
1106 | case OPT_upward_framework: |
1107 | upward = (arg->getOption().getID() == OPT_upward_framework); |
1108 | resolvedPath = ctx.findPathForFramework(arg->getValue()); |
1109 | if (!resolvedPath) { |
1110 | diagnostics << "Unable to find framework for " |
1111 | << arg->getSpelling() << " " << arg->getValue() << "\n"; |
1112 | return false; |
1113 | } else if (ctx.testingFileUsage()) { |
1114 | diagnostics << "Found " << (upward ? "upward " : " ") << "framework " |
1115 | << canonicalizePath(resolvedPath.getValue()) << '\n'; |
1116 | } |
1117 | addFile(resolvedPath.getValue(), ctx, globalWholeArchive, |
1118 | upward, diagnostics); |
1119 | break; |
1120 | case OPT_filelist: |
1121 | if (auto ec = loadFileList(arg->getValue(), |
1122 | ctx, globalWholeArchive, |
1123 | diagnostics)) { |
1124 | handleAllErrors(std::move(ec), [&](const llvm::ErrorInfoBase &EI) { |
1125 | diagnostics << "error: "; |
1126 | EI.log(diagnostics); |
1127 | diagnostics << ", processing '-filelist " << arg->getValue() << "'\n"; |
1128 | }); |
1129 | return false; |
1130 | } |
1131 | break; |
1132 | case OPT_sectcreate: { |
1133 | const char* seg = arg->getValue(0); |
1134 | const char* sect = arg->getValue(1); |
1135 | const char* fileName = arg->getValue(2); |
1136 | |
1137 | ErrorOr<std::unique_ptr<MemoryBuffer>> contentOrErr = |
1138 | MemoryBuffer::getFile(fileName); |
1139 | |
1140 | if (!contentOrErr) { |
1141 | diagnostics << "error: can't open -sectcreate file " << fileName << "\n"; |
1142 | return false; |
1143 | } |
1144 | |
1145 | ctx.addSectCreateSection(seg, sect, std::move(*contentOrErr)); |
1146 | } |
1147 | break; |
1148 | } |
1149 | } |
1150 | |
1151 | if (ctx.getNodes().empty()) { |
1152 | diagnostics << "No input files\n"; |
1153 | return false; |
1154 | } |
1155 | |
1156 | |
1157 | return ctx.validate(diagnostics); |
1158 | } |
1159 | |
1160 | static void createFiles(MachOLinkingContext &ctx, bool Implicit) { |
1161 | std::vector<std::unique_ptr<File>> Files; |
1162 | if (Implicit) |
1163 | ctx.createImplicitFiles(Files); |
1164 | else |
1165 | ctx.createInternalFiles(Files); |
1166 | for (auto i = Files.rbegin(), e = Files.rend(); i != e; ++i) { |
1167 | auto &members = ctx.getNodes(); |
1168 | members.insert(members.begin(), llvm::make_unique<FileNode>(std::move(*i))); |
1169 | } |
1170 | } |
1171 | |
1172 | |
1173 | bool link(llvm::ArrayRef<const char *> args, raw_ostream &diagnostics) { |
1174 | MachOLinkingContext ctx; |
1175 | if (!parse(args, ctx, diagnostics)) |
1176 | return false; |
1177 | if (ctx.doNothing()) |
1178 | return true; |
1179 | if (ctx.getNodes().empty()) |
1180 | return false; |
1181 | |
1182 | for (std::unique_ptr<Node> &ie : ctx.getNodes()) |
1183 | if (FileNode *node = dyn_cast<FileNode>(ie.get())) |
1184 | node->getFile()->parse(); |
1185 | |
1186 | createFiles(ctx, false ); |
1187 | |
1188 | |
1189 | createFiles(ctx, true ); |
1190 | |
1191 | |
1192 | |
1193 | ctx.finalizeInputFiles(); |
1194 | |
1195 | |
1196 | ScopedTask resolveTask(getDefaultDomain(), "Resolve"); |
1197 | Resolver resolver(ctx); |
1198 | if (!resolver.resolve()) |
1199 | return false; |
1200 | SimpleFile *merged = nullptr; |
1201 | { |
1202 | std::unique_ptr<SimpleFile> mergedFile = resolver.resultFile(); |
1203 | merged = mergedFile.get(); |
1204 | auto &members = ctx.getNodes(); |
1205 | members.insert(members.begin(), |
1206 | llvm::make_unique<FileNode>(std::move(mergedFile))); |
1207 | } |
1208 | resolveTask.end(); |
1209 | |
1210 | |
1211 | ScopedTask passTask(getDefaultDomain(), "Passes"); |
1212 | PassManager pm; |
1213 | ctx.addPasses(pm); |
1214 | if (auto ec = pm.runOnFile(*merged)) { |
1215 | |
1216 | |
1217 | diagnostics << "Failed to run passes on file '" << ctx.outputPath() |
1218 | << "': "; |
1219 | logAllUnhandledErrors(std::move(ec), diagnostics, std::string()); |
1220 | return false; |
1221 | } |
1222 | |
1223 | passTask.end(); |
1224 | |
1225 | |
1226 | ScopedTask writeTask(getDefaultDomain(), "Write"); |
1227 | if (auto ec = ctx.writeFile(*merged)) { |
1228 | |
1229 | |
1230 | diagnostics << "Failed to write file '" << ctx.outputPath() << "': "; |
1231 | logAllUnhandledErrors(std::move(ec), diagnostics, std::string()); |
1232 | return false; |
1233 | } |
1234 | |
1235 | return true; |
1236 | } |
1237 | |
1238 | } |
1239 | } |