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