blob: b8f7b4e55d9d2ca7b97748da42578718d1a95864 [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"
Shankar Easwarane44104b2013-08-21 22:57:10 +000011#include "lld/ReaderWriter/MachOFormat.hpp"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000012#include "GOTPass.hpp"
13#include "StubsPass.hpp"
14#include "ReferenceKinds.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000015
16#include "lld/Core/PassManager.h"
17#include "lld/ReaderWriter/Reader.h"
18#include "lld/ReaderWriter/Writer.h"
19#include "lld/Passes/LayoutPass.h"
20
21#include "llvm/ADT/StringExtras.h"
22#include "llvm/ADT/Triple.h"
23
24using lld::mach_o::KindHandler;
25
26namespace lld {
27
Nick Kledzike850d9d2013-09-10 23:46:57 +000028bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
29 result = 0;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000030
31 if (str.empty())
32 return false;
33
34 SmallVector<StringRef, 3> parts;
35 llvm::SplitString(str, parts, ".");
36
37 unsigned long long num;
38 if (llvm::getAsUnsignedInteger(parts[0], 10, num))
39 return true;
40 if (num > 65535)
41 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000042 result = num << 16;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000043
44 if (parts.size() > 1) {
45 if (llvm::getAsUnsignedInteger(parts[1], 10, num))
46 return true;
47 if (num > 255)
48 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000049 result |= (num << 8);
Rui Ueyama0ca149f2013-08-06 22:31:59 +000050 }
51
52 if (parts.size() > 2) {
53 if (llvm::getAsUnsignedInteger(parts[2], 10, num))
54 return true;
55 if (num > 255)
56 return true;
Nick Kledzike850d9d2013-09-10 23:46:57 +000057 result |= num;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000058 }
59
60 return false;
61}
62
Rui Ueyama0ca149f2013-08-06 22:31:59 +000063struct ArchInfo {
64 StringRef archName;
65 MachOLinkingContext::Arch arch;
66 uint32_t cputype;
67 uint32_t cpusubtype;
68};
69
70static ArchInfo archInfos[] = {
71 { "x86_64", MachOLinkingContext::arch_x86_64, mach_o::CPU_TYPE_X86_64,
72 mach_o::CPU_SUBTYPE_X86_64_ALL },
73 { "i386", MachOLinkingContext::arch_x86, mach_o::CPU_TYPE_I386,
74 mach_o::CPU_SUBTYPE_X86_ALL },
75 { "armv6", MachOLinkingContext::arch_armv6, mach_o::CPU_TYPE_ARM,
76 mach_o::CPU_SUBTYPE_ARM_V6 },
77 { "armv7", MachOLinkingContext::arch_armv7, mach_o::CPU_TYPE_ARM,
78 mach_o::CPU_SUBTYPE_ARM_V7 },
79 { "armv7s", MachOLinkingContext::arch_armv7s, mach_o::CPU_TYPE_ARM,
80 mach_o::CPU_SUBTYPE_ARM_V7S },
81 { StringRef(), MachOLinkingContext::arch_unknown, 0, 0 }
82};
83
84MachOLinkingContext::Arch
85MachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
86 for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
87 if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype)) {
88 return info->arch;
89 }
90 }
91 return arch_unknown;
92}
93
94MachOLinkingContext::Arch
95MachOLinkingContext::archFromName(StringRef archName) {
96 for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
97 if (info->archName.equals(archName)) {
98 return info->arch;
99 }
100 }
101 return arch_unknown;
102}
103
104uint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
105 assert(arch != arch_unknown);
106 for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
107 if (info->arch == arch) {
108 return info->cputype;
109 }
110 }
111 llvm_unreachable("Unknown arch type");
112}
113
114uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
115 assert(arch != arch_unknown);
116 for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
117 if (info->arch == arch) {
118 return info->cpusubtype;
119 }
120 }
121 llvm_unreachable("Unknown arch type");
122}
123
124MachOLinkingContext::MachOLinkingContext()
125 : _outputFileType(mach_o::MH_EXECUTE), _outputFileTypeStatic(false),
Nick Kledzike850d9d2013-09-10 23:46:57 +0000126 _doNothing(false), _arch(arch_unknown), _os(OS::macOSX), _osMinVersion(0),
Nick Kledzike773e322013-09-10 23:55:14 +0000127 _pageZeroSize(0x1000), _compatibilityVersion(0), _currentVersion(0),
128 _deadStrippableDylib(false), _kindHandler(nullptr) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000129
130MachOLinkingContext::~MachOLinkingContext() {}
131
132uint32_t MachOLinkingContext::getCPUType() const {
133 return cpuTypeFromArch(_arch);
134}
135
136uint32_t MachOLinkingContext::getCPUSubType() const {
137 return cpuSubtypeFromArch(_arch);
138}
139
140bool MachOLinkingContext::outputTypeHasEntry() const {
141 switch (_outputFileType) {
142 case mach_o::MH_EXECUTE:
143 case mach_o::MH_DYLINKER:
144 case mach_o::MH_PRELOAD:
145 return true;
146 default:
147 return false;
148 }
149}
150
151bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
152 switch (_os) {
Nick Kledzike850d9d2013-09-10 23:46:57 +0000153 case OS::macOSX: {
154 uint32_t parsedVersion;
155 if (parsePackedVersion(mac, parsedVersion))
156 return false;
157 return _osMinVersion >= parsedVersion;
158 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000159 case OS::iOS:
Nick Kledzike850d9d2013-09-10 23:46:57 +0000160 case OS::iOS_simulator: {
161 uint32_t parsedVersion;
162 if (parsePackedVersion(iOS, parsedVersion))
163 return false;
164 return _osMinVersion >= parsedVersion;
165 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000166 }
167 llvm_unreachable("target not configured for iOS or MacOSX");
168}
169
170bool MachOLinkingContext::addEntryPointLoadCommand() const {
171 if ((_outputFileType == mach_o::MH_EXECUTE) && !_outputFileTypeStatic) {
172 return minOS("10.8", "6.0");
173 }
174 return false;
175}
176
177bool MachOLinkingContext::addUnixThreadLoadCommand() const {
178 switch (_outputFileType) {
179 case mach_o::MH_EXECUTE:
180 if (_outputFileTypeStatic)
181 return true;
182 else
183 return !minOS("10.8", "6.0");
184 break;
185 case mach_o::MH_DYLINKER:
186 case mach_o::MH_PRELOAD:
187 return true;
188 default:
189 return false;
190 }
191}
192
193bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000194 if ((_outputFileType == mach_o::MH_EXECUTE) && _entrySymbolName.empty()) {
195 if (_outputFileTypeStatic) {
196 _entrySymbolName = "start";
197 } else {
198 // If targeting newer OS, use _main
199 if (addEntryPointLoadCommand())
200 _entrySymbolName = "_main";
201
202 // If targeting older OS, use start (in crt1.o)
203 if (addUnixThreadLoadCommand())
204 _entrySymbolName = "start";
205 }
206 }
207
Nick Kledzike773e322013-09-10 23:55:14 +0000208 if (_currentVersion && _outputFileType != mach_o::MH_DYLIB) {
209 diagnostics << "error: -current_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000210 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000211 }
212
213 if (_compatibilityVersion && _outputFileType != mach_o::MH_DYLIB) {
214 diagnostics
215 << "error: -compatibility_version can only be used with dylibs\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000216 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000217 }
218
219 if (_deadStrippableDylib && _outputFileType != mach_o::MH_DYLIB) {
220 diagnostics
221 << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000222 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000223 }
224
225 if (!_bundleLoader.empty() && outputFileType() != mach_o::MH_BUNDLE) {
226 diagnostics
227 << "error: -bundle_loader can only be used with Mach-O bundles\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000228 return false;
Nick Kledzike773e322013-09-10 23:55:14 +0000229 }
230
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000231 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000232}
233
234bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) {
235 _os = os;
Nick Kledzike850d9d2013-09-10 23:46:57 +0000236 return parsePackedVersion(minOSVersion, _osMinVersion);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000237}
238
239void MachOLinkingContext::addPasses(PassManager &pm) const {
240 pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
241 pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
242 pm.add(std::unique_ptr<Pass>(new LayoutPass()));
243}
244
245error_code MachOLinkingContext::parseFile(
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000246 LinkerInput &input,
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000247 std::vector<std::unique_ptr<File>> &result) const {
248 // if (!_machoReader)
249 // _machoReader = createReaderMachO(*this);
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000250 // error_code ec = _machoReader->parseFile(input,result);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000251 // if (ec) {
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000252 return _yamlReader->parseFile(input, result);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000253 // }
254
255 return error_code::success();
256}
257
258Writer &MachOLinkingContext::writer() const {
259 if (!_writer) {
260 _writer = createWriterMachO(*this);
261 }
262 return *_writer;
263}
264
265KindHandler &MachOLinkingContext::kindHandler() const {
266 if (!_kindHandler)
267 _kindHandler = KindHandler::create(_arch);
268 return *_kindHandler;
269}
270
271ErrorOr<Reference::Kind>
272MachOLinkingContext::relocKindFromString(StringRef str) const {
273 return kindHandler().stringToKind(str);
274}
275
276ErrorOr<std::string>
277MachOLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
278 return std::string(kindHandler().kindToString(kind));
279}
280
281} // end namespace lld