blob: 005c8f7275fac98f87e06b152d7f976c55dbd813 [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),
118 _compatibilityVersion(0), _currentVersion(0),
Nick Kledzike773e322013-09-10 23:55:14 +0000119 _deadStrippableDylib(false), _kindHandler(nullptr) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000120
121MachOLinkingContext::~MachOLinkingContext() {}
122
123uint32_t MachOLinkingContext::getCPUType() const {
124 return cpuTypeFromArch(_arch);
125}
126
127uint32_t MachOLinkingContext::getCPUSubType() const {
128 return cpuSubtypeFromArch(_arch);
129}
130
Nick Kledzike34182f2013-11-06 21:36:55 +0000131bool MachOLinkingContext::is64Bit(Arch arch) {
132 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
133 if (info->arch == arch) {
134 return (info->cputype & CPU_ARCH_ABI64);
135 }
136 }
137 // unknown archs are not 64-bit.
138 return false;
139}
140
141bool MachOLinkingContext::isHostEndian(Arch arch) {
142 assert(arch != arch_unknown);
143 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
144 if (info->arch == arch) {
145 return (info->littleEndian == llvm::sys::IsLittleEndianHost);
146 }
147 }
148 llvm_unreachable("Unknown arch type");
149}
150
151bool MachOLinkingContext::isBigEndian(Arch arch) {
152 assert(arch != arch_unknown);
153 for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
154 if (info->arch == arch) {
155 return ! info->littleEndian;
156 }
157 }
158 llvm_unreachable("Unknown arch type");
159}
160
161
162
163bool MachOLinkingContext::is64Bit() const {
164 return is64Bit(_arch);
165}
166
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000167bool MachOLinkingContext::outputTypeHasEntry() const {
168 switch (_outputFileType) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000169 case MH_EXECUTE:
170 case MH_DYLINKER:
171 case MH_PRELOAD:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000172 return true;
173 default:
174 return false;
175 }
176}
177
178bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
Nick Kledzik30332b12013-10-08 00:43:34 +0000179 uint32_t parsedVersion;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000180 switch (_os) {
Nick Kledzik30332b12013-10-08 00:43:34 +0000181 case OS::macOSX:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000182 if (parsePackedVersion(mac, parsedVersion))
183 return false;
184 return _osMinVersion >= parsedVersion;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000185 case OS::iOS:
Nick Kledzik30332b12013-10-08 00:43:34 +0000186 case OS::iOS_simulator:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000187 if (parsePackedVersion(iOS, parsedVersion))
188 return false;
189 return _osMinVersion >= parsedVersion;
Nick Kledzik30332b12013-10-08 00:43:34 +0000190 case OS::unknown:
191 break;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000192 }
193 llvm_unreachable("target not configured for iOS or MacOSX");
194}
195
196bool MachOLinkingContext::addEntryPointLoadCommand() const {
Nick Kledzike34182f2013-11-06 21:36:55 +0000197 if ((_outputFileType == MH_EXECUTE) && !_outputFileTypeStatic) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000198 return minOS("10.8", "6.0");
199 }
200 return false;
201}
202
203bool MachOLinkingContext::addUnixThreadLoadCommand() const {
204 switch (_outputFileType) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000205 case MH_EXECUTE:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000206 if (_outputFileTypeStatic)
207 return true;
208 else
209 return !minOS("10.8", "6.0");
210 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000211 case MH_DYLINKER:
212 case MH_PRELOAD:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000213 return true;
214 default:
215 return false;
216 }
217}
218
219bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000220 if ((_outputFileType == MH_EXECUTE) && _entrySymbolName.empty()){
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000221 if (_outputFileTypeStatic) {
222 _entrySymbolName = "start";
223 } else {
224 // If targeting newer OS, use _main
225 if (addEntryPointLoadCommand())
226 _entrySymbolName = "_main";
227
228 // If targeting older OS, use start (in crt1.o)
229 if (addUnixThreadLoadCommand())
230 _entrySymbolName = "start";
231 }
232 }
233
Nick Kledzike34182f2013-11-06 21:36:55 +0000234 // TODO: if -arch not specified, look at arch of first .o file.
235
236 // Set default __PAGEZERO for main executables
237 if ((_outputFileType == MH_EXECUTE) && !_outputFileTypeStatic
238 && (_pageZeroSize == unspecifiedPageZeroSize)) {
239 if (is64Bit(_arch))
240 _pageZeroSize = 0x100000000;
241 else
242 _pageZeroSize = 0x00010000;
243 }
244
245 if (_currentVersion && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000246 diagnostics << "error: -current_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000247 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000248 }
249
Nick Kledzike34182f2013-11-06 21:36:55 +0000250 if (_compatibilityVersion && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000251 diagnostics
252 << "error: -compatibility_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000253 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000254 }
255
Nick Kledzike34182f2013-11-06 21:36:55 +0000256 if (_deadStrippableDylib && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000257 diagnostics
258 << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000259 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000260 }
261
Nick Kledzike34182f2013-11-06 21:36:55 +0000262 if (!_bundleLoader.empty() && outputFileType() != MH_BUNDLE) {
Nick Kledzike773e322013-09-10 23:55:14 +0000263 diagnostics
264 << "error: -bundle_loader can only be used with Mach-O bundles\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000265 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000266 }
267
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000268 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000269}
270
271bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) {
272 _os = os;
Nick Kledzike850d9d2013-09-10 23:46:57 +0000273 return parsePackedVersion(minOSVersion, _osMinVersion);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000274}
275
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000276void MachOLinkingContext::addPasses(PassManager &pm) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000277 if (outputFileType() != MH_OBJECT) {
278 pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
279 pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
280 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000281 pm.add(std::unique_ptr<Pass>(new LayoutPass()));
282}
283
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000284Writer &MachOLinkingContext::writer() const {
285 if (!_writer) {
286 _writer = createWriterMachO(*this);
287 }
288 return *_writer;
289}
290
291KindHandler &MachOLinkingContext::kindHandler() const {
292 if (!_kindHandler)
293 _kindHandler = KindHandler::create(_arch);
294 return *_kindHandler;
295}
296
297ErrorOr<Reference::Kind>
298MachOLinkingContext::relocKindFromString(StringRef str) const {
299 return kindHandler().stringToKind(str);
300}
301
302ErrorOr<std::string>
303MachOLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
304 return std::string(kindHandler().kindToString(kind));
305}
306
307} // end namespace lld