blob: f5dc5c7451fcbf3deb69b964665c1c72a40645be [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 Kledzike34182f2013-11-06 21:36:55 +000024#include "llvm/Support/Host.h"
Nick Kledzik473933b2013-09-27 22:50:00 +000025#include "llvm/Support/MachO.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000026
27using lld::mach_o::KindHandler;
Nick Kledzike34182f2013-11-06 21:36:55 +000028using namespace llvm::MachO;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000029
30namespace lld {
31
Nick Kledzike850d9d2013-09-10 23:46:57 +000032bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
33 result = 0;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000034
35 if (str.empty())
36 return false;
37
38 SmallVector<StringRef, 3> parts;
39 llvm::SplitString(str, parts, ".");
40
41 unsigned long long num;
42 if (llvm::getAsUnsignedInteger(parts[0], 10, num))
43 return true;
44 if (num > 65535)
45 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000046 result = num << 16;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000047
48 if (parts.size() > 1) {
49 if (llvm::getAsUnsignedInteger(parts[1], 10, num))
50 return true;
51 if (num > 255)
52 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000053 result |= (num << 8);
Rui Ueyama0ca149f2013-08-06 22:31:59 +000054 }
55
56 if (parts.size() > 2) {
57 if (llvm::getAsUnsignedInteger(parts[2], 10, num))
58 return true;
59 if (num > 255)
60 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000061 result |= num;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000062 }
63
64 return false;
65}
66
Rui Ueyama0ca149f2013-08-06 22:31:59 +000067
Nick Kledzike34182f2013-11-06 21:36:55 +000068MachOLinkingContext::ArchInfo MachOLinkingContext::_s_archInfos[] = {
69 { "x86_64", arch_x86_64, true, CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL },
70 { "i386", arch_x86, true, CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL },
71 { "ppc", arch_ppc, false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
72 { "armv6", arch_armv6, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6 },
73 { "armv7", arch_armv7, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7 },
74 { "armv7s", arch_armv7s, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S },
75 { "", arch_unknown,false, 0, 0 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000076};
77
78MachOLinkingContext::Arch
79MachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
Nick Kledzike34182f2013-11-06 21:36:55 +000080 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
81 if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype))
Rui Ueyama0ca149f2013-08-06 22:31:59 +000082 return info->arch;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000083 }
84 return arch_unknown;
85}
86
87MachOLinkingContext::Arch
88MachOLinkingContext::archFromName(StringRef archName) {
Nick Kledzike34182f2013-11-06 21:36:55 +000089 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
90 if (info->archName.equals(archName))
Rui Ueyama0ca149f2013-08-06 22:31:59 +000091 return info->arch;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000092 }
93 return arch_unknown;
94}
95
96uint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
97 assert(arch != arch_unknown);
Nick Kledzike34182f2013-11-06 21:36:55 +000098 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
99 if (info->arch == arch)
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000100 return info->cputype;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000101 }
102 llvm_unreachable("Unknown arch type");
103}
104
105uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
106 assert(arch != arch_unknown);
Nick Kledzike34182f2013-11-06 21:36:55 +0000107 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
108 if (info->arch == arch)
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000109 return info->cpusubtype;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000110 }
111 llvm_unreachable("Unknown arch type");
112}
113
114MachOLinkingContext::MachOLinkingContext()
Nick Kledzike34182f2013-11-06 21:36:55 +0000115 : _outputFileType(MH_EXECUTE), _outputFileTypeStatic(false),
Nick Kledzike850d9d2013-09-10 23:46:57 +0000116 _doNothing(false), _arch(arch_unknown), _os(OS::macOSX), _osMinVersion(0),
Nick Kledzike34182f2013-11-06 21:36:55 +0000117 _pageZeroSize(unspecifiedPageZeroSize),
Nick Kledzik705cbc12013-11-08 23:00:26 +0000118 _pageSize(4096),
Nick Kledzike34182f2013-11-06 21:36:55 +0000119 _compatibilityVersion(0), _currentVersion(0),
Nick Kledzike773e322013-09-10 23:55:14 +0000120 _deadStrippableDylib(false), _kindHandler(nullptr) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000121
122MachOLinkingContext::~MachOLinkingContext() {}
123
124uint32_t MachOLinkingContext::getCPUType() const {
125 return cpuTypeFromArch(_arch);
126}
127
128uint32_t MachOLinkingContext::getCPUSubType() const {
129 return cpuSubtypeFromArch(_arch);
130}
131
Nick Kledzike34182f2013-11-06 21:36:55 +0000132bool MachOLinkingContext::is64Bit(Arch arch) {
133 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
134 if (info->arch == arch) {
135 return (info->cputype & CPU_ARCH_ABI64);
136 }
137 }
138 // unknown archs are not 64-bit.
139 return false;
140}
141
142bool MachOLinkingContext::isHostEndian(Arch arch) {
143 assert(arch != arch_unknown);
144 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
145 if (info->arch == arch) {
146 return (info->littleEndian == llvm::sys::IsLittleEndianHost);
147 }
148 }
149 llvm_unreachable("Unknown arch type");
150}
151
152bool MachOLinkingContext::isBigEndian(Arch arch) {
153 assert(arch != arch_unknown);
154 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
155 if (info->arch == arch) {
156 return ! info->littleEndian;
157 }
158 }
159 llvm_unreachable("Unknown arch type");
160}
161
162
163
164bool MachOLinkingContext::is64Bit() const {
165 return is64Bit(_arch);
166}
167
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000168bool MachOLinkingContext::outputTypeHasEntry() const {
169 switch (_outputFileType) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000170 case MH_EXECUTE:
171 case MH_DYLINKER:
172 case MH_PRELOAD:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000173 return true;
174 default:
175 return false;
176 }
177}
178
179bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
Nick Kledzik30332b12013-10-08 00:43:34 +0000180 uint32_t parsedVersion;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000181 switch (_os) {
Nick Kledzik30332b12013-10-08 00:43:34 +0000182 case OS::macOSX:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000183 if (parsePackedVersion(mac, parsedVersion))
184 return false;
185 return _osMinVersion >= parsedVersion;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000186 case OS::iOS:
Nick Kledzik30332b12013-10-08 00:43:34 +0000187 case OS::iOS_simulator:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000188 if (parsePackedVersion(iOS, parsedVersion))
189 return false;
190 return _osMinVersion >= parsedVersion;
Nick Kledzik30332b12013-10-08 00:43:34 +0000191 case OS::unknown:
192 break;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000193 }
194 llvm_unreachable("target not configured for iOS or MacOSX");
195}
196
197bool MachOLinkingContext::addEntryPointLoadCommand() const {
Nick Kledzike34182f2013-11-06 21:36:55 +0000198 if ((_outputFileType == MH_EXECUTE) && !_outputFileTypeStatic) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000199 return minOS("10.8", "6.0");
200 }
201 return false;
202}
203
204bool MachOLinkingContext::addUnixThreadLoadCommand() const {
205 switch (_outputFileType) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000206 case MH_EXECUTE:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000207 if (_outputFileTypeStatic)
208 return true;
209 else
210 return !minOS("10.8", "6.0");
211 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000212 case MH_DYLINKER:
213 case MH_PRELOAD:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000214 return true;
215 default:
216 return false;
217 }
218}
219
220bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000221 if ((_outputFileType == MH_EXECUTE) && _entrySymbolName.empty()){
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000222 if (_outputFileTypeStatic) {
223 _entrySymbolName = "start";
Rui Ueyama3f902b22013-11-12 17:46:55 +0000224 } else if (addUnixThreadLoadCommand()) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000225 // If targeting older OS, use start (in crt1.o)
Rui Ueyama3f902b22013-11-12 17:46:55 +0000226 _entrySymbolName = "start";
227 } else if (addEntryPointLoadCommand()) {
228 // If targeting newer OS, use _main
229 _entrySymbolName = "_main";
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000230 }
231 }
232
Nick Kledzike34182f2013-11-06 21:36:55 +0000233 // TODO: if -arch not specified, look at arch of first .o file.
234
235 // Set default __PAGEZERO for main executables
236 if ((_outputFileType == MH_EXECUTE) && !_outputFileTypeStatic
237 && (_pageZeroSize == unspecifiedPageZeroSize)) {
238 if (is64Bit(_arch))
239 _pageZeroSize = 0x100000000;
240 else
241 _pageZeroSize = 0x00010000;
242 }
243
244 if (_currentVersion && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000245 diagnostics << "error: -current_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000246 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000247 }
248
Nick Kledzike34182f2013-11-06 21:36:55 +0000249 if (_compatibilityVersion && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000250 diagnostics
251 << "error: -compatibility_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000252 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000253 }
254
Nick Kledzike34182f2013-11-06 21:36:55 +0000255 if (_deadStrippableDylib && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000256 diagnostics
257 << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000258 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000259 }
260
Nick Kledzike34182f2013-11-06 21:36:55 +0000261 if (!_bundleLoader.empty() && outputFileType() != MH_BUNDLE) {
Nick Kledzike773e322013-09-10 23:55:14 +0000262 diagnostics
263 << "error: -bundle_loader can only be used with Mach-O bundles\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000264 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000265 }
266
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000267 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000268}
269
270bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) {
271 _os = os;
Nick Kledzike850d9d2013-09-10 23:46:57 +0000272 return parsePackedVersion(minOSVersion, _osMinVersion);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000273}
274
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000275void MachOLinkingContext::addPasses(PassManager &pm) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000276 if (outputFileType() != MH_OBJECT) {
277 pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
278 pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
279 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000280 pm.add(std::unique_ptr<Pass>(new LayoutPass()));
281}
282
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000283Writer &MachOLinkingContext::writer() const {
284 if (!_writer) {
285 _writer = createWriterMachO(*this);
286 }
287 return *_writer;
288}
289
290KindHandler &MachOLinkingContext::kindHandler() const {
291 if (!_kindHandler)
292 _kindHandler = KindHandler::create(_arch);
293 return *_kindHandler;
294}
295
296ErrorOr<Reference::Kind>
297MachOLinkingContext::relocKindFromString(StringRef str) const {
298 return kindHandler().stringToKind(str);
299}
300
301ErrorOr<std::string>
302MachOLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
303 return std::string(kindHandler().kindToString(kind));
304}
305
306} // end namespace lld