blob: 4f5a9bed86b47cf0a97245a4ba070d489eeda0dc [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";
224 } else {
225 // If targeting newer OS, use _main
226 if (addEntryPointLoadCommand())
227 _entrySymbolName = "_main";
228
229 // If targeting older OS, use start (in crt1.o)
230 if (addUnixThreadLoadCommand())
231 _entrySymbolName = "start";
232 }
233 }
234
Nick Kledzike34182f2013-11-06 21:36:55 +0000235 // TODO: if -arch not specified, look at arch of first .o file.
236
237 // Set default __PAGEZERO for main executables
238 if ((_outputFileType == MH_EXECUTE) && !_outputFileTypeStatic
239 && (_pageZeroSize == unspecifiedPageZeroSize)) {
240 if (is64Bit(_arch))
241 _pageZeroSize = 0x100000000;
242 else
243 _pageZeroSize = 0x00010000;
244 }
245
246 if (_currentVersion && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000247 diagnostics << "error: -current_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000248 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000249 }
250
Nick Kledzike34182f2013-11-06 21:36:55 +0000251 if (_compatibilityVersion && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000252 diagnostics
253 << "error: -compatibility_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000254 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000255 }
256
Nick Kledzike34182f2013-11-06 21:36:55 +0000257 if (_deadStrippableDylib && _outputFileType != MH_DYLIB) {
Nick Kledzike773e322013-09-10 23:55:14 +0000258 diagnostics
259 << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000260 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000261 }
262
Nick Kledzike34182f2013-11-06 21:36:55 +0000263 if (!_bundleLoader.empty() && outputFileType() != MH_BUNDLE) {
Nick Kledzike773e322013-09-10 23:55:14 +0000264 diagnostics
265 << "error: -bundle_loader can only be used with Mach-O bundles\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000266 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000267 }
268
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000269 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000270}
271
272bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) {
273 _os = os;
Nick Kledzike850d9d2013-09-10 23:46:57 +0000274 return parsePackedVersion(minOSVersion, _osMinVersion);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000275}
276
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000277void MachOLinkingContext::addPasses(PassManager &pm) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000278 if (outputFileType() != MH_OBJECT) {
279 pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
280 pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
281 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000282 pm.add(std::unique_ptr<Pass>(new LayoutPass()));
283}
284
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000285Writer &MachOLinkingContext::writer() const {
286 if (!_writer) {
287 _writer = createWriterMachO(*this);
288 }
289 return *_writer;
290}
291
292KindHandler &MachOLinkingContext::kindHandler() const {
293 if (!_kindHandler)
294 _kindHandler = KindHandler::create(_arch);
295 return *_kindHandler;
296}
297
298ErrorOr<Reference::Kind>
299MachOLinkingContext::relocKindFromString(StringRef str) const {
300 return kindHandler().stringToKind(str);
301}
302
303ErrorOr<std::string>
304MachOLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
305 return std::string(kindHandler().kindToString(kind));
306}
307
308} // end namespace lld