blob: ad8f8bfa73e25d4ec7db907d31a87d423e68d2ec [file] [log] [blame]
Rui Ueyama0ca149f2013-08-06 22:31:59 +00001//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lld/ReaderWriter/MachOLinkingContext.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000011
12#include "ArchHandler.h"
Nick Kledzik8fc67fb2014-08-13 23:55:41 +000013#include "File.h"
Nick Kledzik635f9c72014-09-04 20:08:30 +000014#include "MachONormalizedFile.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000015#include "MachOPasses.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000016
17#include "lld/Core/PassManager.h"
Nick Kledzik8fc67fb2014-08-13 23:55:41 +000018#include "lld/Driver/DarwinInputGraph.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000019#include "lld/ReaderWriter/Reader.h"
20#include "lld/ReaderWriter/Writer.h"
21#include "lld/Passes/LayoutPass.h"
Shankar Easwaran2bc24922013-10-29 05:12:14 +000022#include "lld/Passes/RoundTripYAMLPass.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000023
24#include "llvm/ADT/StringExtras.h"
25#include "llvm/ADT/Triple.h"
Nick Kledzikbe43d7e2014-09-30 23:15:39 +000026#include "llvm/Config/config.h"
Tim Northover77d82202014-07-10 11:21:06 +000027#include "llvm/Support/Errc.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000028#include "llvm/Support/Host.h"
Nick Kledzik473933b2013-09-27 22:50:00 +000029#include "llvm/Support/MachO.h"
Tim Northover77d82202014-07-10 11:21:06 +000030#include "llvm/Support/Path.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000031
Rui Ueyama57a29532014-08-06 19:37:35 +000032#include <algorithm>
33
Nick Kledzikbe43d7e2014-09-30 23:15:39 +000034#if HAVE_CXXABI_H
35#include <cxxabi.h>
36#endif
37
Nick Kledzik2458bec2014-07-16 19:49:02 +000038using lld::mach_o::ArchHandler;
Nick Kledzik8fc67fb2014-08-13 23:55:41 +000039using lld::mach_o::MachODylibFile;
Nick Kledzike34182f2013-11-06 21:36:55 +000040using namespace llvm::MachO;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000041
42namespace lld {
43
Nick Kledzike850d9d2013-09-10 23:46:57 +000044bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
45 result = 0;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000046
47 if (str.empty())
48 return false;
49
50 SmallVector<StringRef, 3> parts;
51 llvm::SplitString(str, parts, ".");
52
53 unsigned long long num;
54 if (llvm::getAsUnsignedInteger(parts[0], 10, num))
55 return true;
56 if (num > 65535)
57 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000058 result = num << 16;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000059
60 if (parts.size() > 1) {
61 if (llvm::getAsUnsignedInteger(parts[1], 10, num))
62 return true;
63 if (num > 255)
64 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000065 result |= (num << 8);
Rui Ueyama0ca149f2013-08-06 22:31:59 +000066 }
67
68 if (parts.size() > 2) {
69 if (llvm::getAsUnsignedInteger(parts[2], 10, num))
70 return true;
71 if (num > 255)
72 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000073 result |= num;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000074 }
75
76 return false;
77}
78
Rui Ueyama0ca149f2013-08-06 22:31:59 +000079
Nick Kledzike34182f2013-11-06 21:36:55 +000080MachOLinkingContext::ArchInfo MachOLinkingContext::_s_archInfos[] = {
81 { "x86_64", arch_x86_64, true, CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL },
82 { "i386", arch_x86, true, CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL },
83 { "ppc", arch_ppc, false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
84 { "armv6", arch_armv6, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6 },
85 { "armv7", arch_armv7, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7 },
86 { "armv7s", arch_armv7s, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S },
Nick Kledzik1bebb282014-09-09 23:52:59 +000087 { "arm64", arch_arm64, true, CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL },
Nick Kledzike34182f2013-11-06 21:36:55 +000088 { "", arch_unknown,false, 0, 0 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000089};
90
91MachOLinkingContext::Arch
92MachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
Nick Kledzike34182f2013-11-06 21:36:55 +000093 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
94 if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype))
Rui Ueyama0ca149f2013-08-06 22:31:59 +000095 return info->arch;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000096 }
97 return arch_unknown;
98}
99
100MachOLinkingContext::Arch
101MachOLinkingContext::archFromName(StringRef archName) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000102 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
103 if (info->archName.equals(archName))
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000104 return info->arch;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000105 }
106 return arch_unknown;
107}
108
Nick Kledzike5552772013-12-19 21:58:00 +0000109StringRef MachOLinkingContext::nameFromArch(Arch arch) {
110 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
111 if (info->arch == arch)
112 return info->archName;
113 }
114 return "<unknown>";
115}
116
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000117uint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
118 assert(arch != arch_unknown);
Nick Kledzike34182f2013-11-06 21:36:55 +0000119 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
120 if (info->arch == arch)
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000121 return info->cputype;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000122 }
123 llvm_unreachable("Unknown arch type");
124}
125
126uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
127 assert(arch != arch_unknown);
Nick Kledzike34182f2013-11-06 21:36:55 +0000128 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
129 if (info->arch == arch)
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000130 return info->cpusubtype;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000131 }
132 llvm_unreachable("Unknown arch type");
133}
134
Nick Kledzik635f9c72014-09-04 20:08:30 +0000135bool MachOLinkingContext::isThinObjectFile(StringRef path, Arch &arch) {
136 return mach_o::normalized::isThinObjectFile(path, arch);
137}
138
Nick Kledzik14b5d202014-10-08 01:48:10 +0000139bool MachOLinkingContext::sliceFromFatFile(const MemoryBuffer &mb,
140 uint32_t &offset,
141 uint32_t &size) {
142 return mach_o::normalized::sliceFromFatFile(mb, _arch, offset, size);
143}
144
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000145MachOLinkingContext::MachOLinkingContext()
Tim Northoverd30a1f22014-06-20 15:59:00 +0000146 : _outputMachOType(MH_EXECUTE), _outputMachOTypeStatic(false),
Tim Northoveraf3075b2014-09-10 10:39:57 +0000147 _doNothing(false), _pie(false), _arch(arch_unknown), _os(OS::macOSX),
148 _osMinVersion(0), _pageZeroSize(0), _pageSize(4096), _baseAddress(0),
149 _compatibilityVersion(0), _currentVersion(0), _deadStrippableDylib(false),
150 _printAtoms(false), _testingFileUsage(false), _keepPrivateExterns(false),
Nick Kledzikbe43d7e2014-09-30 23:15:39 +0000151 _demangle(false), _archHandler(nullptr),
152 _exportMode(ExportMode::globals) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000153
154MachOLinkingContext::~MachOLinkingContext() {}
155
Nick Kledzik6960b072013-12-21 01:47:17 +0000156void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
157 uint32_t minOSVersion) {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000158 _outputMachOType = type;
Nick Kledzik6960b072013-12-21 01:47:17 +0000159 _arch = arch;
160 _os = os;
161 _osMinVersion = minOSVersion;
162
Nick Kledzikcb2018f2014-10-09 01:01:16 +0000163 // If min OS not specified on command line, use reasonable defaults.
164 if (minOSVersion == 0) {
165 switch (_arch) {
166 case arch_x86_64:
167 case arch_x86:
168 parsePackedVersion("10.8", _osMinVersion);
169 _os = MachOLinkingContext::OS::macOSX;
170 break;
171 case arch_armv6:
172 case arch_armv7:
173 case arch_armv7s:
174 case arch_arm64:
175 parsePackedVersion("7.0", _osMinVersion);
176 _os = MachOLinkingContext::OS::iOS;
177 break;
178 default:
179 break;
180 }
181 }
182
Tim Northoverd30a1f22014-06-20 15:59:00 +0000183 switch (_outputMachOType) {
Nick Kledzik6960b072013-12-21 01:47:17 +0000184 case llvm::MachO::MH_EXECUTE:
185 // If targeting newer OS, use _main
186 if (minOS("10.8", "6.0")) {
187 _entrySymbolName = "_main";
188 } else {
189 // If targeting older OS, use start (in crt1.o)
190 _entrySymbolName = "start";
191 }
192
193 // __PAGEZERO defaults to 4GB on 64-bit (except for PP64 which lld does not
194 // support) and 4KB on 32-bit.
195 if (is64Bit(_arch)) {
196 _pageZeroSize = 0x100000000;
197 } else {
198 _pageZeroSize = 0x1000;
199 }
200
Nick Kledzikb7035ae2014-09-09 00:17:52 +0000201 // Make PIE by default when targetting newer OSs.
202 switch (os) {
203 case OS::macOSX:
204 if (minOSVersion >= 0x000A0700) // MacOSX 10.7
205 _pie = true;
206 break;
207 case OS::iOS:
208 if (minOSVersion >= 0x00040300) // iOS 4.3
209 _pie = true;
210 break;
211 case OS::iOS_simulator:
212 _pie = true;
213 break;
214 case OS::unknown:
215 break;
216 }
Nick Kledzik6960b072013-12-21 01:47:17 +0000217 break;
218 case llvm::MachO::MH_DYLIB:
219 _globalsAreDeadStripRoots = true;
220 break;
221 case llvm::MachO::MH_BUNDLE:
222 break;
223 case llvm::MachO::MH_OBJECT:
224 _printRemainingUndefines = false;
225 _allowRemainingUndefines = true;
226 default:
227 break;
228 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000229
230 // Set default segment page sizes based on arch.
231 if (arch == arch_arm64)
232 _pageSize = 4*4096;
Nick Kledzik6960b072013-12-21 01:47:17 +0000233}
234
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000235uint32_t MachOLinkingContext::getCPUType() const {
236 return cpuTypeFromArch(_arch);
237}
238
239uint32_t MachOLinkingContext::getCPUSubType() const {
240 return cpuSubtypeFromArch(_arch);
241}
242
Nick Kledzike34182f2013-11-06 21:36:55 +0000243bool MachOLinkingContext::is64Bit(Arch arch) {
244 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
245 if (info->arch == arch) {
246 return (info->cputype & CPU_ARCH_ABI64);
247 }
248 }
249 // unknown archs are not 64-bit.
250 return false;
251}
252
253bool MachOLinkingContext::isHostEndian(Arch arch) {
254 assert(arch != arch_unknown);
255 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
256 if (info->arch == arch) {
257 return (info->littleEndian == llvm::sys::IsLittleEndianHost);
258 }
259 }
260 llvm_unreachable("Unknown arch type");
261}
262
263bool MachOLinkingContext::isBigEndian(Arch arch) {
264 assert(arch != arch_unknown);
265 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
266 if (info->arch == arch) {
267 return ! info->littleEndian;
268 }
269 }
270 llvm_unreachable("Unknown arch type");
271}
272
273
274
275bool MachOLinkingContext::is64Bit() const {
276 return is64Bit(_arch);
277}
278
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000279bool MachOLinkingContext::outputTypeHasEntry() const {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000280 switch (_outputMachOType) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000281 case MH_EXECUTE:
282 case MH_DYLINKER:
283 case MH_PRELOAD:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000284 return true;
285 default:
286 return false;
287 }
288}
289
Nick Kledzik2458bec2014-07-16 19:49:02 +0000290bool MachOLinkingContext::needsStubsPass() const {
291 switch (_outputMachOType) {
292 case MH_EXECUTE:
293 return !_outputMachOTypeStatic;
294 case MH_DYLIB:
295 case MH_BUNDLE:
296 return true;
297 default:
298 return false;
299 }
300}
301
302bool MachOLinkingContext::needsGOTPass() const {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000303 // GOT pass not used in -r mode.
304 if (_outputMachOType == MH_OBJECT)
Nick Kledzik2458bec2014-07-16 19:49:02 +0000305 return false;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000306 // Only some arches use GOT pass.
307 switch (_arch) {
308 case arch_x86_64:
309 case arch_arm64:
310 return true;
311 default:
312 return false;
313 }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000314}
315
Tim Northovercf78d372014-09-30 21:29:54 +0000316bool MachOLinkingContext::needsCompactUnwindPass() const {
317 switch (_outputMachOType) {
318 case MH_EXECUTE:
319 case MH_DYLIB:
320 case MH_BUNDLE:
321 return archHandler().needsCompactUnwind();
322 default:
323 return false;
324 }
325}
Nick Kledzik2458bec2014-07-16 19:49:02 +0000326
327StringRef MachOLinkingContext::binderSymbolName() const {
328 return archHandler().stubInfo().binderSymbolName;
329}
330
331
332
333
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000334bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
Nick Kledzik30332b12013-10-08 00:43:34 +0000335 uint32_t parsedVersion;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000336 switch (_os) {
Nick Kledzik30332b12013-10-08 00:43:34 +0000337 case OS::macOSX:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000338 if (parsePackedVersion(mac, parsedVersion))
339 return false;
340 return _osMinVersion >= parsedVersion;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000341 case OS::iOS:
Nick Kledzik30332b12013-10-08 00:43:34 +0000342 case OS::iOS_simulator:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000343 if (parsePackedVersion(iOS, parsedVersion))
344 return false;
345 return _osMinVersion >= parsedVersion;
Nick Kledzik30332b12013-10-08 00:43:34 +0000346 case OS::unknown:
347 break;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000348 }
349 llvm_unreachable("target not configured for iOS or MacOSX");
350}
351
352bool MachOLinkingContext::addEntryPointLoadCommand() const {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000353 if ((_outputMachOType == MH_EXECUTE) && !_outputMachOTypeStatic) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000354 return minOS("10.8", "6.0");
355 }
356 return false;
357}
358
359bool MachOLinkingContext::addUnixThreadLoadCommand() const {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000360 switch (_outputMachOType) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000361 case MH_EXECUTE:
Tim Northoverd30a1f22014-06-20 15:59:00 +0000362 if (_outputMachOTypeStatic)
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000363 return true;
364 else
365 return !minOS("10.8", "6.0");
366 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000367 case MH_DYLINKER:
368 case MH_PRELOAD:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000369 return true;
370 default:
371 return false;
372 }
373}
374
Tim Northover77d82202014-07-10 11:21:06 +0000375bool MachOLinkingContext::pathExists(StringRef path) const {
Nick Kledzik94174f72014-08-15 19:53:41 +0000376 if (!_testingFileUsage)
Tim Northover77d82202014-07-10 11:21:06 +0000377 return llvm::sys::fs::exists(path.str());
378
379 // Otherwise, we're in test mode: only files explicitly provided on the
380 // command-line exist.
Rui Ueyama57a29532014-08-06 19:37:35 +0000381 std::string key = path.str();
382 std::replace(key.begin(), key.end(), '\\', '/');
383 return _existingPaths.find(key) != _existingPaths.end();
Tim Northover77d82202014-07-10 11:21:06 +0000384}
385
Nick Kledzik09d00bb2014-10-04 00:16:13 +0000386bool MachOLinkingContext::fileExists(StringRef path) const {
387 bool found = pathExists(path);
388 // Log search misses.
389 if (!found)
390 addInputFileNotFound(path);
391
392 // When testing, file is never opened, so logging is done here.
393 if (_testingFileUsage && found)
394 addInputFileDependency(path);
395
396 return found;
397}
398
Nick Kledzik2d835da2014-08-14 22:20:41 +0000399void MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) {
400 _syslibRoots = paths;
401}
402
Nick Kledzik8fc67fb2014-08-13 23:55:41 +0000403void MachOLinkingContext::addModifiedSearchDir(StringRef libPath,
404 bool isSystemPath) {
Tim Northover77d82202014-07-10 11:21:06 +0000405 bool addedModifiedPath = false;
406
Nick Kledzik2d835da2014-08-14 22:20:41 +0000407 // -syslibroot only applies to absolute paths.
408 if (libPath.startswith("/")) {
Nick Kledzik8fc67fb2014-08-13 23:55:41 +0000409 for (auto syslibRoot : _syslibRoots) {
Tim Northover77d82202014-07-10 11:21:06 +0000410 SmallString<256> path(syslibRoot);
411 llvm::sys::path::append(path, libPath);
412 if (pathExists(path)) {
413 _searchDirs.push_back(path.str().copy(_allocator));
414 addedModifiedPath = true;
415 }
416 }
417 }
418
419 if (addedModifiedPath)
420 return;
421
422 // Finally, if only one -syslibroot is given, system paths which aren't in it
423 // get suppressed.
Nick Kledzik8fc67fb2014-08-13 23:55:41 +0000424 if (_syslibRoots.size() != 1 || !isSystemPath) {
Tim Northover77d82202014-07-10 11:21:06 +0000425 if (pathExists(libPath)) {
426 _searchDirs.push_back(libPath);
427 }
428 }
429}
430
Nick Kledzik2d835da2014-08-14 22:20:41 +0000431void MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath,
432 bool isSystemPath) {
433 bool pathAdded = false;
434
435 // -syslibroot only used with to absolute framework search paths.
436 if (fwPath.startswith("/")) {
437 for (auto syslibRoot : _syslibRoots) {
438 SmallString<256> path(syslibRoot);
439 llvm::sys::path::append(path, fwPath);
440 if (pathExists(path)) {
441 _frameworkDirs.push_back(path.str().copy(_allocator));
442 pathAdded = true;
443 }
444 }
445 }
446 // If fwPath found in any -syslibroot, then done.
447 if (pathAdded)
448 return;
449
450 // If only one -syslibroot, system paths not in that SDK are suppressed.
451 if (isSystemPath && (_syslibRoots.size() == 1))
452 return;
453
454 // Only use raw fwPath if that directory exists.
455 if (pathExists(fwPath))
456 _frameworkDirs.push_back(fwPath);
457}
458
459
Tim Northover77d82202014-07-10 11:21:06 +0000460ErrorOr<StringRef>
461MachOLinkingContext::searchDirForLibrary(StringRef path,
462 StringRef libName) const {
463 SmallString<256> fullPath;
464 if (libName.endswith(".o")) {
465 // A request ending in .o is special: just search for the file directly.
466 fullPath.assign(path);
467 llvm::sys::path::append(fullPath, libName);
Nick Kledzik09d00bb2014-10-04 00:16:13 +0000468 if (fileExists(fullPath))
Tim Northover77d82202014-07-10 11:21:06 +0000469 return fullPath.str().copy(_allocator);
470 return make_error_code(llvm::errc::no_such_file_or_directory);
471 }
472
473 // Search for dynamic library
474 fullPath.assign(path);
475 llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
Nick Kledzik09d00bb2014-10-04 00:16:13 +0000476 if (fileExists(fullPath))
Tim Northover77d82202014-07-10 11:21:06 +0000477 return fullPath.str().copy(_allocator);
478
479 // If not, try for a static library
480 fullPath.assign(path);
481 llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
Nick Kledzik09d00bb2014-10-04 00:16:13 +0000482 if (fileExists(fullPath))
Tim Northover77d82202014-07-10 11:21:06 +0000483 return fullPath.str().copy(_allocator);
484
485 return make_error_code(llvm::errc::no_such_file_or_directory);
486}
487
488
489
490ErrorOr<StringRef> MachOLinkingContext::searchLibrary(StringRef libName) const {
491 SmallString<256> path;
492 for (StringRef dir : searchDirs()) {
493 ErrorOr<StringRef> ec = searchDirForLibrary(dir, libName);
494 if (ec)
495 return ec;
496 }
497
498 return make_error_code(llvm::errc::no_such_file_or_directory);
499}
500
Nick Kledzik2d835da2014-08-14 22:20:41 +0000501
502ErrorOr<StringRef> MachOLinkingContext::findPathForFramework(StringRef fwName) const{
503 SmallString<256> fullPath;
504 for (StringRef dir : frameworkDirs()) {
505 fullPath.assign(dir);
506 llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName);
Nick Kledzik09d00bb2014-10-04 00:16:13 +0000507 if (fileExists(fullPath))
Nick Kledzik2d835da2014-08-14 22:20:41 +0000508 return fullPath.str().copy(_allocator);
509 }
510
511 return make_error_code(llvm::errc::no_such_file_or_directory);
512}
513
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000514bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000515 // TODO: if -arch not specified, look at arch of first .o file.
516
Tim Northoverd30a1f22014-06-20 15:59:00 +0000517 if (_currentVersion && _outputMachOType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000518 diagnostics << "error: -current_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000519 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000520 }
521
Tim Northoverd30a1f22014-06-20 15:59:00 +0000522 if (_compatibilityVersion && _outputMachOType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000523 diagnostics
524 << "error: -compatibility_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000525 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000526 }
527
Tim Northoverd30a1f22014-06-20 15:59:00 +0000528 if (_deadStrippableDylib && _outputMachOType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000529 diagnostics
530 << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000531 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000532 }
533
Tim Northoverd30a1f22014-06-20 15:59:00 +0000534 if (!_bundleLoader.empty() && outputMachOType() != MH_BUNDLE) {
Nick Kledzike773e322013-09-10 23:55:14 +0000535 diagnostics
536 << "error: -bundle_loader can only be used with Mach-O bundles\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000537 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000538 }
539
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000540 // If -exported_symbols_list used, all exported symbols must be defined.
541 if (_exportMode == ExportMode::whiteList) {
542 for (const auto &symbol : _exportedSymbols)
543 addInitialUndefinedSymbol(symbol.getKey());
544 }
545
Nick Kledzik77afc712014-08-21 20:25:50 +0000546 // If -dead_strip, set up initial live symbols.
547 if (deadStrip()) {
548 // Entry point is live.
549 if (outputTypeHasEntry())
550 addDeadStripRoot(entrySymbolName());
551 // Lazy binding helper is live.
552 if (needsStubsPass())
553 addDeadStripRoot(binderSymbolName());
554 // If using -exported_symbols_list, make all exported symbols live.
555 if (_exportMode == ExportMode::whiteList) {
556 _globalsAreDeadStripRoots = false;
557 for (const auto &symbol : _exportedSymbols)
558 addDeadStripRoot(symbol.getKey());
559 }
560 }
561
Nick Kledzik09d00bb2014-10-04 00:16:13 +0000562 addOutputFileDependency(outputPath());
563
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000564 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000565}
566
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000567void MachOLinkingContext::addPasses(PassManager &pm) {
Nico Rieckb9d84f42014-02-24 21:14:37 +0000568 pm.add(std::unique_ptr<Pass>(new LayoutPass(registry())));
Nick Kledzik2458bec2014-07-16 19:49:02 +0000569 if (needsStubsPass())
570 mach_o::addStubsPass(pm, *this);
Tim Northovercf78d372014-09-30 21:29:54 +0000571 if (needsCompactUnwindPass())
572 mach_o::addCompactUnwindPass(pm, *this);
Nick Kledzik2458bec2014-07-16 19:49:02 +0000573 if (needsGOTPass())
574 mach_o::addGOTPass(pm, *this);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000575}
576
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000577Writer &MachOLinkingContext::writer() const {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000578 if (!_writer)
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000579 _writer = createWriterMachO(*this);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000580 return *_writer;
581}
582
Nick Kledzik22c90732014-10-01 20:24:30 +0000583MachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) {
584 std::unique_ptr<MachOFileNode> node(new MachOFileNode(path, false, *this));
Nick Kledzik8fc67fb2014-08-13 23:55:41 +0000585 std::error_code ec = node->parse(*this, llvm::errs());
586 if (ec)
587 return nullptr;
588
589 assert(node->files().size() == 1 && "expected one file in dylib");
590 // lld::File object is owned by MachOFileNode object. This method returns
591 // an unowned pointer to the lld::File object.
592 MachODylibFile* result = reinterpret_cast<MachODylibFile*>(
593 node->files().front().get());
594
595 // Node object now owned by _indirectDylibs vector.
596 _indirectDylibs.push_back(std::move(node));
597
598 return result;
599}
600
601
Nick Kledzik22c90732014-10-01 20:24:30 +0000602MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) {
Nick Kledzik8fc67fb2014-08-13 23:55:41 +0000603 // See if already loaded.
604 auto pos = _pathToDylibMap.find(path);
605 if (pos != _pathToDylibMap.end())
606 return pos->second;
607
608 // Search -L paths if of the form "libXXX.dylib"
609 std::pair<StringRef, StringRef> split = path.rsplit('/');
610 StringRef leafName = split.second;
611 if (leafName.startswith("lib") && leafName.endswith(".dylib")) {
612 // FIXME: Need to enhance searchLibrary() to only look for .dylib
613 auto libPath = searchLibrary(leafName);
614 if (!libPath.getError()) {
615 return loadIndirectDylib(libPath.get());
616 }
617 }
618
619 // Try full path with sysroot.
620 for (StringRef sysPath : _syslibRoots) {
621 SmallString<256> fullPath;
622 fullPath.assign(sysPath);
623 llvm::sys::path::append(fullPath, path);
624 if (pathExists(fullPath))
625 return loadIndirectDylib(fullPath);
626 }
627
628 // Try full path.
629 if (pathExists(path)) {
630 return loadIndirectDylib(path);
631 }
632
633 return nullptr;
634}
635
636bool MachOLinkingContext::createImplicitFiles(
Nick Kledzik22c90732014-10-01 20:24:30 +0000637 std::vector<std::unique_ptr<File> > &result) {
Nick Kledzik8fc67fb2014-08-13 23:55:41 +0000638 // Add indirect dylibs by asking each linked dylib to add its indirects.
639 // Iterate until no more dylibs get loaded.
640 size_t dylibCount = 0;
641 while (dylibCount != _allDylibs.size()) {
642 dylibCount = _allDylibs.size();
643 for (MachODylibFile *dylib : _allDylibs) {
644 dylib->loadReExportedDylibs([this] (StringRef path) -> MachODylibFile* {
645 return findIndirectDylib(path); });
646 }
647 }
648
649 // Let writer add output type specific extras.
650 return writer().createImplicitFiles(result);
651}
652
653
Nick Kledzik14b5d202014-10-08 01:48:10 +0000654void MachOLinkingContext::registerDylib(MachODylibFile *dylib) const {
Nick Kledzik8fc67fb2014-08-13 23:55:41 +0000655 _allDylibs.insert(dylib);
656 _pathToDylibMap[dylib->installName()] = dylib;
657 // If path is different than install name, register path too.
658 if (!dylib->path().equals(dylib->installName()))
659 _pathToDylibMap[dylib->path()] = dylib;
660}
661
662
Nick Kledzik2458bec2014-07-16 19:49:02 +0000663ArchHandler &MachOLinkingContext::archHandler() const {
664 if (!_archHandler)
665 _archHandler = ArchHandler::create(_arch);
666 return *_archHandler;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000667}
668
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000669
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000670void MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect,
671 uint8_t align2) {
672 SectionAlign entry;
673 entry.segmentName = seg;
674 entry.sectionName = sect;
675 entry.align2 = align2;
676 _sectAligns.push_back(entry);
677}
678
679bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
680 uint8_t &align2) const {
681 for (const SectionAlign &entry : _sectAligns) {
682 if (seg.equals(entry.segmentName) && sect.equals(entry.sectionName)) {
683 align2 = entry.align2;
684 return true;
685 }
686 }
687 return false;
688}
689
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000690
691void MachOLinkingContext::addExportSymbol(StringRef sym) {
692 // FIXME: Support wildcards.
693 _exportedSymbols.insert(sym);
694}
695
696bool MachOLinkingContext::exportSymbolNamed(StringRef sym) const {
697 switch (_exportMode) {
698 case ExportMode::globals:
699 llvm_unreachable("exportSymbolNamed() should not be called in this mode");
700 break;
701 case ExportMode::whiteList:
702 return _exportedSymbols.count(sym);
703 case ExportMode::blackList:
704 return !_exportedSymbols.count(sym);
705 }
Yaron Keren9682c852014-09-21 05:07:44 +0000706 llvm_unreachable("_exportMode unknown enum value");
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000707}
708
Nick Kledzikbe43d7e2014-09-30 23:15:39 +0000709std::string MachOLinkingContext::demangle(StringRef symbolName) const {
710 // Only try to demangle symbols if -demangle on command line
711 if (!_demangle)
712 return symbolName;
713
714 // Only try to demangle symbols that look like C++ symbols
715 if (!symbolName.startswith("__Z"))
716 return symbolName;
717
718#if HAVE_CXXABI_H
719 SmallString<256> symBuff;
720 StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
721 // Mach-O has extra leading underscore that needs to be removed.
722 const char *cstr = nullTermSym.data() + 1;
723 int status;
724 char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
725 if (demangled != NULL) {
726 std::string result(demangled);
727 // __cxa_demangle() always uses a malloc'ed buffer to return the result.
728 free(demangled);
729 return result;
730 }
731#endif
732
733 return symbolName;
734}
735
Nick Kledzik09d00bb2014-10-04 00:16:13 +0000736std::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
737 std::error_code ec;
738 _dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>(new
739 llvm::raw_fd_ostream(path, ec, llvm::sys::fs::F_None));
740 if (ec) {
741 _dependencyInfo.reset();
742 return ec;
743 }
744
745 char linkerVersionOpcode = 0x00;
746 *_dependencyInfo << linkerVersionOpcode;
747 *_dependencyInfo << "lld"; // FIXME
748 *_dependencyInfo << '\0';
749
750 return std::error_code();
751}
752
753void MachOLinkingContext::addInputFileDependency(StringRef path) const {
754 if (!_dependencyInfo)
755 return;
756
757 char inputFileOpcode = 0x10;
758 *_dependencyInfo << inputFileOpcode;
759 *_dependencyInfo << path;
760 *_dependencyInfo << '\0';
761}
762
763void MachOLinkingContext::addInputFileNotFound(StringRef path) const {
764 if (!_dependencyInfo)
765 return;
766
767 char inputFileOpcode = 0x11;
768 *_dependencyInfo << inputFileOpcode;
769 *_dependencyInfo << path;
770 *_dependencyInfo << '\0';
771}
772
773void MachOLinkingContext::addOutputFileDependency(StringRef path) const {
774 if (!_dependencyInfo)
775 return;
776
777 char outputFileOpcode = 0x40;
778 *_dependencyInfo << outputFileOpcode;
779 *_dependencyInfo << path;
780 *_dependencyInfo << '\0';
781}
782
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000783
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000784} // end namespace lld