blob: b79fd39a8bcd2a16d461b5d8213aa686f60a7e6d [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"
11#include "GOTPass.hpp"
12#include "StubsPass.hpp"
13#include "ReferenceKinds.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000014
15#include "lld/Core/PassManager.h"
16#include "lld/ReaderWriter/Reader.h"
17#include "lld/ReaderWriter/Writer.h"
18#include "lld/Passes/LayoutPass.h"
Shankar Easwaran2bc24922013-10-29 05:12:14 +000019#include "lld/Passes/RoundTripNativePass.h"
20#include "lld/Passes/RoundTripYAMLPass.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000021
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/ADT/Triple.h"
Nick Kledzik473933b2013-09-27 22:50:00 +000024#include "llvm/Support/MachO.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000025
26using lld::mach_o::KindHandler;
27
28namespace lld {
29
Nick Kledzike850d9d2013-09-10 23:46:57 +000030bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
31 result = 0;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000032
33 if (str.empty())
34 return false;
35
36 SmallVector<StringRef, 3> parts;
37 llvm::SplitString(str, parts, ".");
38
39 unsigned long long num;
40 if (llvm::getAsUnsignedInteger(parts[0], 10, num))
41 return true;
42 if (num > 65535)
43 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000044 result = num << 16;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000045
46 if (parts.size() > 1) {
47 if (llvm::getAsUnsignedInteger(parts[1], 10, num))
48 return true;
49 if (num > 255)
50 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000051 result |= (num << 8);
Rui Ueyama0ca149f2013-08-06 22:31:59 +000052 }
53
54 if (parts.size() > 2) {
55 if (llvm::getAsUnsignedInteger(parts[2], 10, num))
56 return true;
57 if (num > 255)
58 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000059 result |= num;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000060 }
61
62 return false;
63}
64
Rui Ueyama0ca149f2013-08-06 22:31:59 +000065struct ArchInfo {
66 StringRef archName;
67 MachOLinkingContext::Arch arch;
68 uint32_t cputype;
69 uint32_t cpusubtype;
70};
71
72static ArchInfo archInfos[] = {
Nick Kledzik473933b2013-09-27 22:50:00 +000073 { "x86_64", MachOLinkingContext::arch_x86_64, llvm::MachO::CPU_TYPE_X86_64,
74 llvm::MachO::CPU_SUBTYPE_X86_64_ALL },
75 { "i386", MachOLinkingContext::arch_x86, llvm::MachO::CPU_TYPE_I386,
76 llvm::MachO::CPU_SUBTYPE_X86_ALL },
77 { "armv6", MachOLinkingContext::arch_armv6, llvm::MachO::CPU_TYPE_ARM,
78 llvm::MachO::CPU_SUBTYPE_ARM_V6 },
79 { "armv7", MachOLinkingContext::arch_armv7, llvm::MachO::CPU_TYPE_ARM,
80 llvm::MachO::CPU_SUBTYPE_ARM_V7 },
81 { "armv7s", MachOLinkingContext::arch_armv7s, llvm::MachO::CPU_TYPE_ARM,
82 llvm::MachO::CPU_SUBTYPE_ARM_V7S },
Rui Ueyama0ca149f2013-08-06 22:31:59 +000083 { StringRef(), MachOLinkingContext::arch_unknown, 0, 0 }
84};
85
86MachOLinkingContext::Arch
87MachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
88 for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
89 if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype)) {
90 return info->arch;
91 }
92 }
93 return arch_unknown;
94}
95
96MachOLinkingContext::Arch
97MachOLinkingContext::archFromName(StringRef archName) {
98 for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
99 if (info->archName.equals(archName)) {
100 return info->arch;
101 }
102 }
103 return arch_unknown;
104}
105
106uint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
107 assert(arch != arch_unknown);
108 for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
109 if (info->arch == arch) {
110 return info->cputype;
111 }
112 }
113 llvm_unreachable("Unknown arch type");
114}
115
116uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
117 assert(arch != arch_unknown);
118 for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
119 if (info->arch == arch) {
120 return info->cpusubtype;
121 }
122 }
123 llvm_unreachable("Unknown arch type");
124}
125
126MachOLinkingContext::MachOLinkingContext()
Nick Kledzik473933b2013-09-27 22:50:00 +0000127 : _outputFileType(llvm::MachO::MH_EXECUTE), _outputFileTypeStatic(false),
Nick Kledzike850d9d2013-09-10 23:46:57 +0000128 _doNothing(false), _arch(arch_unknown), _os(OS::macOSX), _osMinVersion(0),
Nick Kledzike773e322013-09-10 23:55:14 +0000129 _pageZeroSize(0x1000), _compatibilityVersion(0), _currentVersion(0),
130 _deadStrippableDylib(false), _kindHandler(nullptr) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000131
132MachOLinkingContext::~MachOLinkingContext() {}
133
134uint32_t MachOLinkingContext::getCPUType() const {
135 return cpuTypeFromArch(_arch);
136}
137
138uint32_t MachOLinkingContext::getCPUSubType() const {
139 return cpuSubtypeFromArch(_arch);
140}
141
142bool MachOLinkingContext::outputTypeHasEntry() const {
143 switch (_outputFileType) {
Nick Kledzik473933b2013-09-27 22:50:00 +0000144 case llvm::MachO::MH_EXECUTE:
145 case llvm::MachO::MH_DYLINKER:
146 case llvm::MachO::MH_PRELOAD:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000147 return true;
148 default:
149 return false;
150 }
151}
152
153bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
Nick Kledzik30332b12013-10-08 00:43:34 +0000154 uint32_t parsedVersion;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000155 switch (_os) {
Nick Kledzik30332b12013-10-08 00:43:34 +0000156 case OS::macOSX:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000157 if (parsePackedVersion(mac, parsedVersion))
158 return false;
159 return _osMinVersion >= parsedVersion;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000160 case OS::iOS:
Nick Kledzik30332b12013-10-08 00:43:34 +0000161 case OS::iOS_simulator:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000162 if (parsePackedVersion(iOS, parsedVersion))
163 return false;
164 return _osMinVersion >= parsedVersion;
Nick Kledzik30332b12013-10-08 00:43:34 +0000165 case OS::unknown:
166 break;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000167 }
168 llvm_unreachable("target not configured for iOS or MacOSX");
169}
170
171bool MachOLinkingContext::addEntryPointLoadCommand() const {
Nick Kledzik473933b2013-09-27 22:50:00 +0000172 if ((_outputFileType == llvm::MachO::MH_EXECUTE) && !_outputFileTypeStatic) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000173 return minOS("10.8", "6.0");
174 }
175 return false;
176}
177
178bool MachOLinkingContext::addUnixThreadLoadCommand() const {
179 switch (_outputFileType) {
Nick Kledzik473933b2013-09-27 22:50:00 +0000180 case llvm::MachO::MH_EXECUTE:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000181 if (_outputFileTypeStatic)
182 return true;
183 else
184 return !minOS("10.8", "6.0");
185 break;
Nick Kledzik473933b2013-09-27 22:50:00 +0000186 case llvm::MachO::MH_DYLINKER:
187 case llvm::MachO::MH_PRELOAD:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000188 return true;
189 default:
190 return false;
191 }
192}
193
194bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
Nick Kledzik473933b2013-09-27 22:50:00 +0000195 if ((_outputFileType == llvm::MachO::MH_EXECUTE) && _entrySymbolName.empty()){
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000196 if (_outputFileTypeStatic) {
197 _entrySymbolName = "start";
198 } else {
199 // If targeting newer OS, use _main
200 if (addEntryPointLoadCommand())
201 _entrySymbolName = "_main";
202
203 // If targeting older OS, use start (in crt1.o)
204 if (addUnixThreadLoadCommand())
205 _entrySymbolName = "start";
206 }
207 }
208
Nick Kledzik473933b2013-09-27 22:50:00 +0000209 if (_currentVersion && _outputFileType != llvm::MachO::MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000210 diagnostics << "error: -current_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000211 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000212 }
213
Nick Kledzik473933b2013-09-27 22:50:00 +0000214 if (_compatibilityVersion && _outputFileType != llvm::MachO::MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000215 diagnostics
216 << "error: -compatibility_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000217 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000218 }
219
Nick Kledzik473933b2013-09-27 22:50:00 +0000220 if (_deadStrippableDylib && _outputFileType != llvm::MachO::MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000221 diagnostics
222 << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000223 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000224 }
225
Nick Kledzik473933b2013-09-27 22:50:00 +0000226 if (!_bundleLoader.empty() && outputFileType() != llvm::MachO::MH_BUNDLE) {
Nick Kledzike773e322013-09-10 23:55:14 +0000227 diagnostics
228 << "error: -bundle_loader can only be used with Mach-O bundles\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000229 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000230 }
231
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000232 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000233}
234
235bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) {
236 _os = os;
Nick Kledzike850d9d2013-09-10 23:46:57 +0000237 return parsePackedVersion(minOSVersion, _osMinVersion);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000238}
239
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000240void MachOLinkingContext::addPasses(PassManager &pm) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000241 pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
242 pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
243 pm.add(std::unique_ptr<Pass>(new LayoutPass()));
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000244#ifndef NDEBUG
245 pm.add(std::unique_ptr<Pass>(new RoundTripYAMLPass(*this)));
246 pm.add(std::unique_ptr<Pass>(new RoundTripNativePass(*this)));
247#endif
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000248}
249
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000250Writer &MachOLinkingContext::writer() const {
251 if (!_writer) {
252 _writer = createWriterMachO(*this);
253 }
254 return *_writer;
255}
256
257KindHandler &MachOLinkingContext::kindHandler() const {
258 if (!_kindHandler)
259 _kindHandler = KindHandler::create(_arch);
260 return *_kindHandler;
261}
262
263ErrorOr<Reference::Kind>
264MachOLinkingContext::relocKindFromString(StringRef str) const {
265 return kindHandler().stringToKind(str);
266}
267
268ErrorOr<std::string>
269MachOLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
270 return std::string(kindHandler().kindToString(kind));
271}
272
273} // end namespace lld