]>
Commit | Line | Data |
---|---|---|
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- | |
2 | * | |
3 | * Copyright (c) 2005-2010 Apple Inc. All rights reserved. | |
4 | * | |
5 | * @APPLE_LICENSE_HEADER_START@ | |
6 | * | |
7 | * This file contains Original Code and/or Modifications of Original Code | |
8 | * as defined in and that are subject to the Apple Public Source License | |
9 | * Version 2.0 (the 'License'). You may not use this file except in | |
10 | * compliance with the License. Please obtain a copy of the License at | |
11 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
12 | * file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
19 | * Please see the License for the specific language governing rights and | |
20 | * limitations under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | ||
25 | ||
26 | #ifndef __LD_HPP__ | |
27 | #define __LD_HPP__ | |
28 | ||
29 | #include <stdint.h> | |
30 | #include <math.h> | |
31 | #include <unistd.h> | |
32 | #include <assert.h> | |
33 | ||
34 | #include <set> | |
35 | #include <map> | |
36 | #include <vector> | |
37 | #include <string> | |
38 | #include <unordered_set> | |
39 | ||
40 | #include "configure.h" | |
41 | ||
42 | namespace ld { | |
43 | ||
44 | // | |
45 | // platform | |
46 | // | |
47 | ||
48 | enum Platform { | |
49 | kPlatform_unknown=0, | |
50 | kPlatform_macOS=1, | |
51 | kPlatform_iOS=2, | |
52 | kPlatform_tvOS=3, | |
53 | kPlatform_watchOS=4, | |
54 | kPlatform_bridgeOS=5, | |
55 | kPlatform_iOSMac=6, | |
56 | kPlatform_iOSSimulator=7, | |
57 | kPlatform_tvOSSimulator=8, | |
58 | kPlatform_watchOSSimulator=9 | |
59 | }; | |
60 | ||
61 | typedef std::set<Platform> PlatformSet; | |
62 | ||
63 | // | |
64 | // minumum OS versions | |
65 | // | |
66 | ||
67 | typedef std::pair<Platform, uint32_t> Version; | |
68 | ||
69 | struct VersionSet { | |
70 | private: | |
71 | std::map<Platform, uint32_t> _versions; | |
72 | public: | |
73 | VersionSet() {} | |
74 | VersionSet(const std::map<Platform, uint32_t>& P) : _versions(P) {} | |
75 | void add(ld::Version platformVersion) { | |
76 | _versions.insert(platformVersion); | |
77 | } | |
78 | void erase(const Platform& platform) { | |
79 | _versions.erase(platform); | |
80 | } | |
81 | size_t count() const { return _versions.size(); } | |
82 | size_t empty() const { return _versions.empty(); } | |
83 | ||
84 | void forEach(void (^callback)(ld::Platform platform, uint32_t version, bool &stop)) const { | |
85 | bool stop = false; | |
86 | for (const auto& version : _versions) { | |
87 | callback(version.first, version.second, stop); | |
88 | if (stop) | |
89 | return; | |
90 | } | |
91 | } | |
92 | ||
93 | bool contains(ld::Platform platform) const { return _versions.count(platform) != 0; } | |
94 | bool contains(ld::PlatformSet platforms) const { | |
95 | __block bool retval = true; | |
96 | forEach(^(ld::Platform platform, uint32_t version, bool &stop) { | |
97 | if (platforms.find(platform) == platforms.end()) { | |
98 | stop = true; | |
99 | retval = false; | |
100 | } | |
101 | }); | |
102 | return retval; | |
103 | } | |
104 | ||
105 | uint32_t minOS(const ld::Platform& platform) const { | |
106 | for (const auto& version : _versions) { | |
107 | if (basePlatform(version.first) == platform) { | |
108 | return version.second; | |
109 | } | |
110 | } | |
111 | return 0; | |
112 | } | |
113 | ||
114 | bool minOS(const Version& version) const { | |
115 | return minOS(version.first) >= version.second; | |
116 | } | |
117 | ||
118 | const ld::Platform basePlatform(const ld::Platform& platform) const { | |
119 | switch(platform) { | |
120 | case kPlatform_iOSMac: | |
121 | case kPlatform_iOSSimulator: | |
122 | return kPlatform_iOS; | |
123 | case kPlatform_watchOSSimulator: | |
124 | return kPlatform_watchOS; | |
125 | case kPlatform_tvOSSimulator: | |
126 | return kPlatform_tvOS; | |
127 | default: | |
128 | return platform; | |
129 | } | |
130 | } | |
131 | ||
132 | bool minOS(const ld::VersionSet& requiredMinVersions) const { | |
133 | __block bool retval = true; | |
134 | forEach(^(ld::Platform platform, uint32_t version, bool &stop) { | |
135 | if (!requiredMinVersions.contains(basePlatform(platform))) | |
136 | return; | |
137 | if (version < requiredMinVersions.minOS(basePlatform(platform))) { | |
138 | stop = true; | |
139 | retval = false; | |
140 | } | |
141 | }); | |
142 | return retval; | |
143 | } | |
144 | ||
145 | std::string to_str() const { | |
146 | std::string retval; | |
147 | auto appendPlatform = [&](const std::string& platform) { | |
148 | if (retval.empty()) { | |
149 | retval = platform; | |
150 | } else { | |
151 | retval += "/"; | |
152 | retval += platform; | |
153 | } | |
154 | }; | |
155 | ||
156 | forEach(^(ld::Platform platform, uint32_t version, bool &stop) { | |
157 | switch (platform) { | |
158 | case ld::kPlatform_macOS: appendPlatform("macOS"); break; | |
159 | case ld::kPlatform_iOSMac: appendPlatform("iOSMac"); break; | |
160 | case ld::kPlatform_iOS: appendPlatform("iOS"); break; | |
161 | case ld::kPlatform_iOSSimulator: appendPlatform("iOS Simulator"); break; | |
162 | case ld::kPlatform_watchOS: appendPlatform("watchOS"); break; | |
163 | case ld::kPlatform_watchOSSimulator: appendPlatform("watchOS Simulator"); break; | |
164 | case ld::kPlatform_tvOS: appendPlatform("tvOS"); break; | |
165 | case ld::kPlatform_tvOSSimulator: appendPlatform("tvOS Simulator"); break; | |
166 | case ld::kPlatform_bridgeOS: appendPlatform("bridgeOS"); break; | |
167 | case ld::kPlatform_unknown: appendPlatform("Unkown"); break; | |
168 | } | |
169 | }); | |
170 | ||
171 | return retval; | |
172 | } | |
173 | }; | |
174 | ||
175 | static const Version mac10_4 ({kPlatform_macOS, 0x000A0400}); | |
176 | static const Version mac10_5 ({kPlatform_macOS, 0x000A0500}); | |
177 | static const Version mac10_6 ({kPlatform_macOS, 0x000A0600}); | |
178 | static const Version mac10_7 ({kPlatform_macOS, 0x000A0700}); | |
179 | static const Version mac10_8 ({kPlatform_macOS, 0x000A0800}); | |
180 | static const Version mac10_9 ({kPlatform_macOS, 0x000A0900}); | |
181 | static const Version mac10_12 ({kPlatform_macOS, 0x000A0C00}); | |
182 | static const Version mac10_14 ({kPlatform_macOS, 0x000A0E00}); | |
183 | static const Version mac10_Future ({kPlatform_macOS, 0x10000000}); | |
184 | ||
185 | static const Version iOS_2_0 ({kPlatform_iOS, 0x00020000}); | |
186 | static const Version iOS_3_1 ({kPlatform_iOS, 0x00030100}); | |
187 | static const Version iOS_4_2 ({kPlatform_iOS, 0x00040200}); | |
188 | static const Version iOS_4_3 ({kPlatform_iOS, 0x00040300}); | |
189 | static const Version iOS_5_0 ({kPlatform_iOS, 0x00050000}); | |
190 | static const Version iOS_6_0 ({kPlatform_iOS, 0x00060000}); | |
191 | static const Version iOS_7_0 ({kPlatform_iOS, 0x00070000}); | |
192 | static const Version iOS_8_0 ({kPlatform_iOS, 0x00080000}); | |
193 | static const Version iOS_9_0 ({kPlatform_iOS, 0x00090000}); | |
194 | static const Version iOS_10_0 ({kPlatform_iOS, 0x000A0000}); | |
195 | static const Version iOS_11_0 ({kPlatform_iOS, 0x000B0000}); | |
196 | static const Version iOS_12_0 ({kPlatform_iOS, 0x000C0000}); | |
197 | static const Version iOS_Future ({kPlatform_iOS, 0x10000000}); | |
198 | ||
199 | static const Version watchOS_1_0 ({kPlatform_watchOS, 0x00010000}); | |
200 | static const Version watchOS_2_0 ({kPlatform_watchOS, 0x00020000}); | |
201 | static const Version watchOS_5_0 ({kPlatform_watchOS, 0x00050000}); | |
202 | static const Version watchOS_Future ({kPlatform_watchOS, 0x10000000}); | |
203 | ||
204 | static const Version tvOS_9_0 ({kPlatform_tvOS, 0x00090000}); | |
205 | static const Version tvOS_12_0 ({kPlatform_tvOS, 0x000C0000}); | |
206 | static const Version tvOS_Future ({kPlatform_tvOS, 0x10000000}); | |
207 | ||
208 | static const Version bridgeOS_1_0 ({kPlatform_bridgeOS, 0x00010000}); | |
209 | static const Version bridgeOS_Future ({kPlatform_bridgeOS, 0x10000000}); | |
210 | ||
211 | // Platform Sets | |
212 | ||
213 | static const PlatformSet simulatorPlatforms ( {kPlatform_iOSSimulator, kPlatform_tvOSSimulator, kPlatform_watchOSSimulator} ); | |
214 | ||
215 | //FIXME do we need to add simulatots to these? | |
216 | //FIXME Are the dates correct? | |
217 | static const VersionSet version2007 ({mac10_4, iOS_2_0}); | |
218 | static const VersionSet version2008 ({mac10_5, iOS_2_0}); | |
219 | static const VersionSet version2008Fall ({mac10_5, iOS_3_1}); | |
220 | static const VersionSet version2009 ({mac10_6, iOS_3_1}); | |
221 | static const VersionSet version2010 ({mac10_7, iOS_4_2}); | |
222 | static const VersionSet version2010Fall ({mac10_7, iOS_4_3}); | |
223 | ||
224 | static const VersionSet version2012 ({mac10_8, iOS_6_0}); | |
225 | static const VersionSet version2013 ({mac10_9, iOS_7_0}); | |
226 | ||
227 | static const VersionSet supportsSplitSegV2 ({mac10_12, iOS_9_0, watchOS_2_0, tvOS_9_0}); | |
228 | // FIXME: Use the comment out line instead. | |
229 | static const VersionSet supportsLCBuildVersion ({mac10_14, iOS_12_0, watchOS_5_0, tvOS_12_0, bridgeOS_1_0}); | |
230 | static const VersionSet supportsPIE ({mac10_5, iOS_4_2}); | |
231 | static const VersionSet supportsTLV ({mac10_7, iOS_9_0}); | |
232 | ||
233 | // Forward declaration for bitcode support | |
234 | class Bitcode; | |
235 | ||
236 | // | |
237 | // ld::File | |
238 | // | |
239 | // Abstract base class for all object or library files the linker processes. | |
240 | // | |
241 | // forEachAtom() iterates over the Atoms in the order they occur in the file. | |
242 | // | |
243 | // justInTimeforEachAtom(name) iterates over lazily created Atoms. For instance if | |
244 | // File is a static library, justInTimeforEachAtom() will iterate over the base set | |
245 | // of Atoms from the archive member implementing 'name'. | |
246 | // | |
247 | class File | |
248 | { | |
249 | public: | |
250 | ||
251 | class AtomHandler { | |
252 | public: | |
253 | virtual ~AtomHandler() {} | |
254 | virtual void doAtom(const class Atom&) = 0; | |
255 | virtual void doFile(const class File&) = 0; | |
256 | }; | |
257 | ||
258 | // | |
259 | // ld::File::Ordinal | |
260 | // | |
261 | // Codifies the rules of ordering input files for symbol precedence. These are: | |
262 | // - Input files listed on the command line are ordered according to their index in the argument list. | |
263 | // - Input files listed in a file list are ordered first at the index of the file list argument, then | |
264 | // by index in the file list | |
265 | // - Input files extracted from archives are ordered using the ordinal of the archive itself plus the | |
266 | // index of the object file within the archive | |
267 | // - Indirect dylibs are ordered after all input files derived from the command line, in the order that | |
268 | // they are discovered. | |
269 | // - The LTO object file is last. | |
270 | // | |
271 | class Ordinal | |
272 | { | |
273 | private: | |
274 | // The actual numeric ordinal. Lower values have higher precedence and a zero value is invalid. | |
275 | // The 64 bit ordinal is broken into 4 16 bit chunks. The high 16 bits are a "partition" that | |
276 | // is used to distinguish major ordinal groups: command line, indirect dylib, LTO. | |
277 | // The remaining chunks are used according to the partition (see below). | |
278 | uint64_t _ordinal; | |
279 | ||
280 | Ordinal (uint64_t ordinal) : _ordinal(ordinal) {} | |
281 | ||
282 | enum { kArgListPartition=0, kIndirectDylibPartition=1, kLTOPartition = 2, kLinkerOptionPartition = 3, InvalidParition=0xffff }; | |
283 | Ordinal(uint16_t partition, uint16_t majorIndex, uint16_t minorIndex, uint16_t counter) { | |
284 | _ordinal = ((uint64_t)partition<<48) | ((uint64_t)majorIndex<<32) | ((uint64_t)minorIndex<<16) | ((uint64_t)counter<<0); | |
285 | } | |
286 | ||
287 | const uint16_t partition() const { return (_ordinal>>48)&0xffff; } | |
288 | const uint16_t majorIndex() const { return (_ordinal>>32)&0xffff; } | |
289 | const uint16_t minorIndex() const { return (_ordinal>>16)&0xffff; } | |
290 | const uint16_t counter() const { return (_ordinal>>00)&0xffff; } | |
291 | ||
292 | const Ordinal nextMajorIndex() const { assert(majorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<32)); } | |
293 | const Ordinal nextMinorIndex() const { assert(minorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<16)); } | |
294 | const Ordinal nextCounter() const { assert(counter() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<0)); } | |
295 | ||
296 | public: | |
297 | Ordinal() : _ordinal(0) {}; | |
298 | ||
299 | static const Ordinal NullOrdinal() { return Ordinal((uint64_t)0); } | |
300 | ||
301 | const bool validOrdinal() const { return _ordinal != 0; } | |
302 | ||
303 | bool operator ==(const Ordinal& rhs) const { return _ordinal == rhs._ordinal; } | |
304 | bool operator !=(const Ordinal& rhs) const { return _ordinal != rhs._ordinal; } | |
305 | bool operator < (const Ordinal& rhs) const { return _ordinal < rhs._ordinal; } | |
306 | bool operator > (const Ordinal& rhs) const { return _ordinal > rhs._ordinal; } | |
307 | ||
308 | // For ordinals derived from the command line args the partition is ArgListPartition | |
309 | // The majorIndex is the arg index that pulls in the file, file list, or archive. | |
310 | // The minorIndex is used for files pulled in by a file list and the value is the index of the file in the file list. | |
311 | // The counter is used for .a files and the value is the index of the object in the archive. | |
312 | // Thus, an object pulled in from a .a that was listed in a file list could use all three fields. | |
313 | static const Ordinal makeArgOrdinal(uint16_t argIndex) { return Ordinal(kArgListPartition, argIndex, 0, 0); }; | |
314 | const Ordinal nextFileListOrdinal() const { return nextMinorIndex(); } | |
315 | const Ordinal archiveOrdinalWithMemberIndex(uint16_t memberIndex) const { return Ordinal(partition(), majorIndex(), minorIndex(), memberIndex); } | |
316 | ||
317 | // For indirect libraries the partition is IndirectDylibPartition and the counter is used or order the libraries. | |
318 | static const ld::File::Ordinal indirectDylibBase() { return Ordinal(kIndirectDylibPartition, 0, 0, 0); } | |
319 | const Ordinal nextIndirectDylibOrdinal() const { return nextCounter(); } | |
320 | ||
321 | // For the LTO mach-o the partition is LTOPartition. As there is only one LTO file no other fields are needed. | |
322 | static const ld::File::Ordinal LTOOrdinal() { return Ordinal(kLTOPartition, 0, 0, 0); } | |
323 | ||
324 | // For linker options embedded in object files | |
325 | static const ld::File::Ordinal linkeOptionBase() { return Ordinal(kIndirectDylibPartition, 1, 0, 0); } | |
326 | const Ordinal nextLinkerOptionOrdinal() { return nextCounter(); }; | |
327 | ||
328 | }; | |
329 | ||
330 | typedef enum { Reloc, Dylib, Archive, Other } Type; | |
331 | ||
332 | File(const char* pth, time_t modTime, Ordinal ord, Type type) | |
333 | : _path(pth), _modTime(modTime), _ordinal(ord), _type(type) { } | |
334 | virtual ~File() {} | |
335 | const char* path() const { return _path; } | |
336 | time_t modificationTime() const{ return _modTime; } | |
337 | Ordinal ordinal() const { return _ordinal; } | |
338 | virtual bool forEachAtom(AtomHandler&) const = 0; | |
339 | virtual bool justInTimeforEachAtom(const char* name, AtomHandler&) const = 0; | |
340 | virtual uint8_t swiftVersion() const { return 0; } | |
341 | virtual uint32_t cpuSubType() const { return 0; } | |
342 | virtual uint32_t subFileCount() const { return 1; } | |
343 | virtual const VersionSet& platforms() const { return _platforms; } | |
344 | bool fileExists() const { return _modTime != 0; } | |
345 | Type type() const { return _type; } | |
346 | virtual Bitcode* getBitcode() const { return NULL; } | |
347 | private: | |
348 | const char* _path; | |
349 | time_t _modTime; | |
350 | const Ordinal _ordinal; | |
351 | const Type _type; | |
352 | // Note this is just a placeholder as platforms() needs something to return | |
353 | static const VersionSet _platforms; | |
354 | }; | |
355 | ||
356 | namespace relocatable { | |
357 | // | |
358 | // ld::relocatable::File | |
359 | // | |
360 | // Abstract base class for object files the linker processes. | |
361 | // | |
362 | // debugInfo() returns if the object file contains debugger information (stabs or dwarf). | |
363 | // | |
364 | // stabs() lazily creates a vector of Stab objects for each atom | |
365 | // | |
366 | // canScatterAtoms() true for all compiler generated code. Hand written assembly can opt-in | |
367 | // via .subsections_via_symbols directive. When true it means the linker can break up section | |
368 | // content at symbol boundaries and do optimizations like coalescing, dead code stripping, or | |
369 | // apply order files. | |
370 | // | |
371 | // optimize() used by libLTO to lazily generate code from llvm bit-code files | |
372 | // | |
373 | class File : public ld::File | |
374 | { | |
375 | public: | |
376 | enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 }; | |
377 | enum SourceKind { kSourceUnknown=0, kSourceObj, kSourceLTO, kSourceArchive, kSourceCompilerArchive }; | |
378 | struct Stab { | |
379 | const class Atom* atom; | |
380 | uint8_t type; | |
381 | uint8_t other; | |
382 | uint16_t desc; | |
383 | uint32_t value; | |
384 | const char* string; | |
385 | }; | |
386 | typedef const std::vector< std::vector<const char*> > LinkerOptionsList; | |
387 | typedef std::vector<std::pair<uint32_t,uint32_t>> ToolVersionList; | |
388 | struct AstTimeAndPath { uint64_t time; std::string path; }; | |
389 | ||
390 | File(const char* pth, time_t modTime, Ordinal ord) | |
391 | : ld::File(pth, modTime, ord, Reloc) { } | |
392 | virtual ~File() {} | |
393 | virtual DebugInfoKind debugInfo() const = 0; | |
394 | virtual const char* debugInfoPath() const { return path(); } | |
395 | virtual time_t debugInfoModificationTime() const { return modificationTime(); } | |
396 | virtual const std::vector<Stab>* stabs() const = 0; | |
397 | virtual bool canScatterAtoms() const = 0; | |
398 | virtual bool hasLongBranchStubs() { return false; } | |
399 | virtual bool hasllvmProfiling() const { return false; } | |
400 | virtual bool hasObjC() const { return false; } | |
401 | virtual bool objcHasCategoryClassPropertiesField() const { return false; } | |
402 | virtual LinkerOptionsList* linkerOptions() const = 0; | |
403 | virtual const ToolVersionList& toolVersions() const = 0; | |
404 | virtual SourceKind sourceKind() const { return kSourceUnknown; } | |
405 | virtual const uint8_t* fileContent() const { return nullptr; } | |
406 | virtual const std::vector<AstTimeAndPath>* astFiles() const { return nullptr; } | |
407 | }; | |
408 | } // namespace relocatable | |
409 | ||
410 | ||
411 | namespace dylib { | |
412 | ||
413 | // | |
414 | // ld::dylib::File | |
415 | // | |
416 | // Abstract base class for dynamic shared libraries read by the linker processes. | |
417 | // | |
418 | class File : public ld::File | |
419 | { | |
420 | public: | |
421 | class DylibHandler | |
422 | { | |
423 | public: | |
424 | virtual ~DylibHandler() {} | |
425 | virtual File* findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative) = 0; | |
426 | }; | |
427 | ||
428 | File(const char* pth, time_t modTime, Ordinal ord) | |
429 | : ld::File(pth, modTime, ord, Dylib), _dylibInstallPath(NULL), _frameworkName(NULL), | |
430 | _dylibTimeStamp(0), _dylibCurrentVersion(0), _dylibCompatibilityVersion(0), | |
431 | _explicitlyLinked(false), _implicitlyLinked(false), _speculativelyLoaded(false), | |
432 | _lazyLoadedDylib(false), _forcedWeakLinked(false), _reExported(false), | |
433 | _upward(false), _dead(false) { } | |
434 | const char* installPath() const { return _dylibInstallPath; } | |
435 | const char* frameworkName() const { return _frameworkName; } | |
436 | uint32_t timestamp() const { return _dylibTimeStamp; } | |
437 | uint32_t currentVersion() const { return _dylibCurrentVersion; } | |
438 | uint32_t compatibilityVersion() const{ return _dylibCompatibilityVersion; } | |
439 | void setExplicitlyLinked() { _explicitlyLinked = true; } | |
440 | bool explicitlyLinked() const { return _explicitlyLinked; } | |
441 | void setImplicitlyLinked() { _implicitlyLinked = true; } | |
442 | bool implicitlyLinked() const { return _implicitlyLinked; } | |
443 | void setSpeculativelyLoaded() { _speculativelyLoaded = true; } | |
444 | bool speculativelyLoaded() const { return _speculativelyLoaded; } | |
445 | ||
446 | // attributes of how dylib will be used when linked | |
447 | void setWillBeLazyLoadedDylb() { _lazyLoadedDylib = true; } | |
448 | bool willBeLazyLoadedDylib() const { return _lazyLoadedDylib; } | |
449 | void setForcedWeakLinked() { _forcedWeakLinked = true; } | |
450 | bool forcedWeakLinked() const { return _forcedWeakLinked; } | |
451 | ||
452 | void setWillBeReExported() { _reExported = true; } | |
453 | bool willBeReExported() const { return _reExported; } | |
454 | void setWillBeUpwardDylib() { _upward = true; } | |
455 | bool willBeUpwardDylib() const { return _upward; } | |
456 | void setWillBeRemoved(bool value) { _dead = value; } | |
457 | bool willRemoved() const { return _dead; } | |
458 | ||
459 | virtual void processIndirectLibraries(DylibHandler* handler, bool addImplicitDylibs) = 0; | |
460 | virtual bool providedExportAtom() const = 0; | |
461 | virtual const char* parentUmbrella() const = 0; | |
462 | virtual const std::vector<const char*>* allowableClients() const = 0; | |
463 | virtual const std::vector<const char*>& rpaths() const = 0; | |
464 | virtual bool hasWeakExternals() const = 0; | |
465 | virtual bool deadStrippable() const = 0; | |
466 | virtual bool hasWeakDefinition(const char* name) const = 0; | |
467 | virtual bool hasPublicInstallName() const = 0; | |
468 | virtual bool allSymbolsAreWeakImported() const = 0; | |
469 | virtual bool installPathVersionSpecific() const { return false; } | |
470 | virtual bool appExtensionSafe() const = 0; | |
471 | ||
472 | public: | |
473 | const char* _dylibInstallPath; | |
474 | const char* _frameworkName; | |
475 | uint32_t _dylibTimeStamp; | |
476 | uint32_t _dylibCurrentVersion; | |
477 | uint32_t _dylibCompatibilityVersion; | |
478 | bool _explicitlyLinked; | |
479 | bool _implicitlyLinked; | |
480 | bool _speculativelyLoaded; | |
481 | bool _lazyLoadedDylib; | |
482 | bool _forcedWeakLinked; | |
483 | bool _reExported; | |
484 | bool _upward; | |
485 | bool _dead; | |
486 | }; | |
487 | } // namespace dylib | |
488 | ||
489 | ||
490 | namespace archive { | |
491 | // | |
492 | // ld::archive::File | |
493 | // | |
494 | // Abstract base class for static libraries read by the linker processes. | |
495 | // | |
496 | class File : public ld::File | |
497 | { | |
498 | public: | |
499 | File(const char* pth, time_t modTime, Ordinal ord) | |
500 | : ld::File(pth, modTime, ord, Archive) { } | |
501 | virtual ~File() {} | |
502 | virtual bool justInTimeDataOnlyforEachAtom(const char* name, AtomHandler&) const = 0; | |
503 | }; | |
504 | } // namespace archive | |
505 | ||
506 | ||
507 | // | |
508 | // ld::Section | |
509 | // | |
510 | class Section | |
511 | { | |
512 | public: | |
513 | enum Type { typeUnclassified, typeCode, typePageZero, typeImportProxies, typeLinkEdit, typeMachHeader, typeStack, | |
514 | typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO, typeTempAlias, | |
515 | typeCString, typeNonStdCString, typeCStringPointer, typeUTF16Strings, typeCFString, typeObjC1Classes, | |
516 | typeCFI, typeLSDA, typeDtraceDOF, typeUnwindInfo, typeObjCClassRefs, typeObjC2CategoryList, | |
517 | typeZeroFill, typeTentativeDefs, typeLazyPointer, typeStub, typeNonLazyPointer, typeDyldInfo, | |
518 | typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers, | |
519 | typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols, typeThreadStarts, | |
520 | typeTLVDefs, typeTLVZeroFill, typeTLVInitialValues, typeTLVInitializerPointers, typeTLVPointers, | |
521 | typeFirstSection, typeLastSection, typeDebug, typeSectCreate }; | |
522 | ||
523 | ||
524 | Section(const char* sgName, const char* sctName, | |
525 | Type t, bool hidden=false) | |
526 | : _segmentName(sgName), _sectionName(sctName), | |
527 | _type(t), _hidden(hidden) {} | |
528 | Section(const Section& sect) | |
529 | : _segmentName(sect.segmentName()), _sectionName(sect.sectionName()), | |
530 | _type(sect.type()), _hidden(sect.isSectionHidden()) {} | |
531 | ||
532 | bool operator==(const Section& rhs) const { return ( (_hidden==rhs._hidden) && | |
533 | (strcmp(_segmentName, rhs._segmentName)==0) && | |
534 | (strcmp(_sectionName, rhs._sectionName)==0) ); } | |
535 | bool operator!=(const Section& rhs) const { return ! (*this == rhs); } | |
536 | const char* segmentName() const { return _segmentName; } | |
537 | const char* sectionName() const { return _sectionName; } | |
538 | Type type() const { return _type; } | |
539 | bool isSectionHidden() const { return _hidden; } | |
540 | ||
541 | private: | |
542 | const char* _segmentName; | |
543 | const char* _sectionName; | |
544 | Type _type; | |
545 | bool _hidden; | |
546 | }; | |
547 | ||
548 | ||
549 | ||
550 | // | |
551 | // ld::Fixup | |
552 | // | |
553 | // A Fixup describes how part of an Atom's content must be fixed up. For instance, | |
554 | // an instruction may contain a displacement to another Atom that must be | |
555 | // fixed up by the linker. | |
556 | // | |
557 | // A Fixup my reference another Atom. There are two kinds of references: direct and by-name. | |
558 | // With a direct reference, the target is bound by the File that created it. | |
559 | // For instance a reference to a static would produce a direct reference. | |
560 | // A by-name reference requires the linker to find the target Atom with the | |
561 | // required name in order to be bound. | |
562 | // | |
563 | // For a link to succeed all Fixup must be bound. | |
564 | // | |
565 | // A Reference also has a fix-up-offset. This is the offset into the content of the | |
566 | // Atom holding the reference where the fix-up (relocation) will be applied. | |
567 | // | |
568 | // | |
569 | struct Fixup | |
570 | { | |
571 | enum TargetBinding { bindingNone, bindingByNameUnbound, bindingDirectlyBound, bindingByContentBound, bindingsIndirectlyBound }; | |
572 | enum Cluster { k1of1, k1of2, k2of2, k1of3, k2of3, k3of3, k1of4, k2of4, k3of4, k4of4, k1of5, k2of5, k3of5, k4of5, k5of5 }; | |
573 | enum Kind { kindNone, kindNoneFollowOn, | |
574 | // grouping | |
575 | kindNoneGroupSubordinate, | |
576 | kindNoneGroupSubordinateFDE, kindNoneGroupSubordinateLSDA, kindNoneGroupSubordinatePersonality, | |
577 | // value calculations | |
578 | kindSetTargetAddress, | |
579 | kindSubtractTargetAddress, | |
580 | kindAddAddend, | |
581 | kindSubtractAddend, | |
582 | kindSetTargetImageOffset, | |
583 | kindSetTargetSectionOffset, | |
584 | kindSetTargetTLVTemplateOffset, | |
585 | // pointer store kinds (of current calculated value) | |
586 | kindStore8, | |
587 | kindStoreLittleEndian16, | |
588 | kindStoreLittleEndianLow24of32, | |
589 | kindStoreLittleEndian32, | |
590 | kindStoreLittleEndian64, | |
591 | kindStoreBigEndian16, | |
592 | kindStoreBigEndianLow24of32, | |
593 | kindStoreBigEndian32, | |
594 | kindStoreBigEndian64, | |
595 | // Intel specific store kinds | |
596 | kindStoreX86BranchPCRel8, kindStoreX86BranchPCRel32, | |
597 | kindStoreX86PCRel8, kindStoreX86PCRel16, | |
598 | kindStoreX86PCRel32, kindStoreX86PCRel32_1, kindStoreX86PCRel32_2, kindStoreX86PCRel32_4, | |
599 | kindStoreX86PCRel32GOTLoad, kindStoreX86PCRel32GOTLoadNowLEA, kindStoreX86PCRel32GOT, | |
600 | kindStoreX86PCRel32TLVLoad, kindStoreX86PCRel32TLVLoadNowLEA, | |
601 | kindStoreX86Abs32TLVLoad, kindStoreX86Abs32TLVLoadNowLEA, | |
602 | // ARM specific store kinds | |
603 | kindStoreARMBranch24, kindStoreThumbBranch22, | |
604 | kindStoreARMLoad12, | |
605 | kindStoreARMLow16, kindStoreARMHigh16, | |
606 | kindStoreThumbLow16, kindStoreThumbHigh16, | |
607 | #if SUPPORT_ARCH_arm64 | |
608 | // ARM64 specific store kinds | |
609 | kindStoreARM64Branch26, | |
610 | kindStoreARM64Page21, kindStoreARM64PageOff12, | |
611 | kindStoreARM64GOTLoadPage21, kindStoreARM64GOTLoadPageOff12, | |
612 | kindStoreARM64GOTLeaPage21, kindStoreARM64GOTLeaPageOff12, | |
613 | kindStoreARM64TLVPLoadPage21, kindStoreARM64TLVPLoadPageOff12, | |
614 | kindStoreARM64TLVPLoadNowLeaPage21, kindStoreARM64TLVPLoadNowLeaPageOff12, | |
615 | kindStoreARM64PointerToGOT, kindStoreARM64PCRelToGOT, | |
616 | #endif | |
617 | // dtrace probes | |
618 | kindDtraceExtra, | |
619 | kindStoreX86DtraceCallSiteNop, kindStoreX86DtraceIsEnableSiteClear, | |
620 | kindStoreARMDtraceCallSiteNop, kindStoreARMDtraceIsEnableSiteClear, | |
621 | kindStoreARM64DtraceCallSiteNop, kindStoreARM64DtraceIsEnableSiteClear, | |
622 | kindStoreThumbDtraceCallSiteNop, kindStoreThumbDtraceIsEnableSiteClear, | |
623 | // lazy binding | |
624 | kindLazyTarget, kindSetLazyOffset, | |
625 | // islands | |
626 | kindIslandTarget, | |
627 | // data-in-code markers | |
628 | kindDataInCodeStartData, kindDataInCodeStartJT8, kindDataInCodeStartJT16, | |
629 | kindDataInCodeStartJT32, kindDataInCodeStartJTA32, kindDataInCodeEnd, | |
630 | // linker optimization hints | |
631 | kindLinkerOptimizationHint, | |
632 | // pointer store combinations | |
633 | kindStoreTargetAddressLittleEndian32, // kindSetTargetAddress + kindStoreLittleEndian32 | |
634 | kindStoreTargetAddressLittleEndian64, // kindSetTargetAddress + kindStoreLittleEndian64 | |
635 | kindStoreTargetAddressBigEndian32, // kindSetTargetAddress + kindStoreBigEndian32 | |
636 | kindStoreTargetAddressBigEndian64, // kindSetTargetAddress + kindStoreBigEndian364 | |
637 | kindSetTargetTLVTemplateOffsetLittleEndian32, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian32 | |
638 | kindSetTargetTLVTemplateOffsetLittleEndian64, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian64 | |
639 | // Intel value calculation and store combinations | |
640 | kindStoreTargetAddressX86PCRel32, // kindSetTargetAddress + kindStoreX86PCRel32 | |
641 | kindStoreTargetAddressX86BranchPCRel32, // kindSetTargetAddress + kindStoreX86BranchPCRel32 | |
642 | kindStoreTargetAddressX86PCRel32GOTLoad,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoad | |
643 | kindStoreTargetAddressX86PCRel32GOTLoadNowLEA,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoadNowLEA | |
644 | kindStoreTargetAddressX86PCRel32TLVLoad, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoad | |
645 | kindStoreTargetAddressX86PCRel32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoadNowLEA | |
646 | kindStoreTargetAddressX86Abs32TLVLoad, // kindSetTargetAddress + kindStoreX86Abs32TLVLoad | |
647 | kindStoreTargetAddressX86Abs32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86Abs32TLVLoadNowLEA | |
648 | // ARM value calculation and store combinations | |
649 | kindStoreTargetAddressARMBranch24, // kindSetTargetAddress + kindStoreARMBranch24 | |
650 | kindStoreTargetAddressThumbBranch22, // kindSetTargetAddress + kindStoreThumbBranch22 | |
651 | kindStoreTargetAddressARMLoad12, // kindSetTargetAddress + kindStoreARMLoad12 | |
652 | #if SUPPORT_ARCH_arm64 | |
653 | // ARM64 value calculation and store combinations | |
654 | kindStoreTargetAddressARM64Branch26, // kindSetTargetAddress + kindStoreARM64Branch26 | |
655 | kindStoreTargetAddressARM64Page21, // kindSetTargetAddress + kindStoreARM64Page21 | |
656 | kindStoreTargetAddressARM64PageOff12, // kindSetTargetAddress + kindStoreARM64PageOff12 | |
657 | kindStoreTargetAddressARM64GOTLoadPage21, // kindSetTargetAddress + kindStoreARM64GOTLoadPage21 | |
658 | kindStoreTargetAddressARM64GOTLoadPageOff12,// kindSetTargetAddress + kindStoreARM64GOTLoadPageOff12 | |
659 | kindStoreTargetAddressARM64GOTLeaPage21, // kindSetTargetAddress + kindStoreARM64GOTLeaPage21 | |
660 | kindStoreTargetAddressARM64GOTLeaPageOff12, // kindSetTargetAddress + kindStoreARM64GOTLeaPageOff12 | |
661 | kindStoreTargetAddressARM64TLVPLoadPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadPage21 | |
662 | kindStoreTargetAddressARM64TLVPLoadPageOff12,// kindSetTargetAddress + kindStoreARM64TLVPLoadPageOff12 | |
663 | kindStoreTargetAddressARM64TLVPLoadNowLeaPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPage21 | |
664 | kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPageOff12 | |
665 | #endif | |
666 | #if SUPPORT_ARCH_arm64e | |
667 | kindStoreLittleEndianAuth64, | |
668 | kindStoreTargetAddressLittleEndianAuth64, // kindSetTargetAddress + kindStoreLittleEndianAuth64 | |
669 | kindSetAuthData, | |
670 | #endif | |
671 | }; | |
672 | ||
673 | #if SUPPORT_ARCH_arm64e | |
674 | struct AuthData { | |
675 | // clang encodes the combination of the key bits as these values. | |
676 | typedef enum { | |
677 | ptrauth_key_asia = 0, | |
678 | ptrauth_key_asib = 1, | |
679 | ptrauth_key_asda = 2, | |
680 | ptrauth_key_asdb = 3, | |
681 | } ptrauth_key; | |
682 | ||
683 | uint16_t discriminator; | |
684 | bool hasAddressDiversity; | |
685 | ptrauth_key key; | |
686 | }; | |
687 | #endif | |
688 | ||
689 | union { | |
690 | const Atom* target; | |
691 | const char* name; | |
692 | uint64_t addend; | |
693 | uint32_t bindingIndex; | |
694 | #if SUPPORT_ARCH_arm64e | |
695 | AuthData authData; | |
696 | #endif | |
697 | } u; | |
698 | uint32_t offsetInAtom; | |
699 | Kind kind : 8; | |
700 | Cluster clusterSize : 4; | |
701 | bool weakImport : 1; | |
702 | TargetBinding binding : 3; | |
703 | bool contentAddendOnly : 1; | |
704 | bool contentDetlaToAddendOnly : 1; | |
705 | bool contentIgnoresAddend : 1; | |
706 | ||
707 | typedef Fixup* iterator; | |
708 | ||
709 | Fixup() : | |
710 | offsetInAtom(0), kind(kindNone), clusterSize(k1of1), weakImport(false), | |
711 | binding(bindingNone), | |
712 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) { u.target = NULL; } | |
713 | ||
714 | Fixup(Kind k, Atom* targetAtom) : | |
715 | offsetInAtom(0), kind(k), clusterSize(k1of1), weakImport(false), | |
716 | binding(Fixup::bindingDirectlyBound), | |
717 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) | |
718 | { assert(targetAtom != NULL); u.target = targetAtom; } | |
719 | ||
720 | Fixup(uint32_t off, Cluster c, Kind k) : | |
721 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), | |
722 | binding(Fixup::bindingNone), | |
723 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) | |
724 | { u.addend = 0; } | |
725 | ||
726 | Fixup(uint32_t off, Cluster c, Kind k, bool weakIm, const char* name) : | |
727 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(weakIm), | |
728 | binding(Fixup::bindingByNameUnbound), | |
729 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) | |
730 | { assert(name != NULL); u.name = name; } | |
731 | ||
732 | Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const char* name) : | |
733 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b), | |
734 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) | |
735 | { assert(name != NULL); u.name = name; } | |
736 | ||
737 | Fixup(uint32_t off, Cluster c, Kind k, const Atom* targetAtom) : | |
738 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), | |
739 | binding(Fixup::bindingDirectlyBound), | |
740 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) | |
741 | { assert(targetAtom != NULL); u.target = targetAtom; } | |
742 | ||
743 | Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const Atom* targetAtom) : | |
744 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b), | |
745 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) | |
746 | { assert(targetAtom != NULL); u.target = targetAtom; } | |
747 | ||
748 | Fixup(uint32_t off, Cluster c, Kind k, uint64_t addend) : | |
749 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), | |
750 | binding(Fixup::bindingNone), | |
751 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) | |
752 | { u.addend = addend; } | |
753 | ||
754 | #if SUPPORT_ARCH_arm64e | |
755 | Fixup(uint32_t off, Cluster c, Kind k, AuthData authData) : | |
756 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), | |
757 | binding(Fixup::bindingNone), | |
758 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) | |
759 | { u.authData = authData; } | |
760 | #endif | |
761 | ||
762 | Fixup(Kind k, uint32_t lohKind, uint32_t off1, uint32_t off2) : | |
763 | offsetInAtom(off1), kind(k), clusterSize(k1of1), | |
764 | weakImport(false), binding(Fixup::bindingNone), contentAddendOnly(false), | |
765 | contentDetlaToAddendOnly(false), contentIgnoresAddend(false) { | |
766 | assert(k == kindLinkerOptimizationHint); | |
767 | LOH_arm64 extra; | |
768 | extra.addend = 0; | |
769 | extra.info.kind = lohKind; | |
770 | extra.info.count = 1; | |
771 | extra.info.delta1 = 0; | |
772 | extra.info.delta2 = (off2 - off1) >> 2; | |
773 | u.addend = extra.addend; | |
774 | } | |
775 | ||
776 | ||
777 | bool firstInCluster() const { | |
778 | switch (clusterSize) { | |
779 | case k1of1: | |
780 | case k1of2: | |
781 | case k1of3: | |
782 | case k1of4: | |
783 | case k1of5: | |
784 | return true; | |
785 | default: | |
786 | break; | |
787 | } | |
788 | return false; | |
789 | } | |
790 | ||
791 | bool lastInCluster() const { | |
792 | switch (clusterSize) { | |
793 | case k1of1: | |
794 | case k2of2: | |
795 | case k3of3: | |
796 | case k4of4: | |
797 | case k5of5: | |
798 | return true; | |
799 | default: | |
800 | break; | |
801 | } | |
802 | return false; | |
803 | } | |
804 | ||
805 | bool isStore() const { | |
806 | switch ( kind ) { | |
807 | case ld::Fixup::kindNone: | |
808 | case ld::Fixup::kindNoneFollowOn: | |
809 | case ld::Fixup::kindNoneGroupSubordinate: | |
810 | case ld::Fixup::kindNoneGroupSubordinateFDE: | |
811 | case ld::Fixup::kindNoneGroupSubordinateLSDA: | |
812 | case ld::Fixup::kindNoneGroupSubordinatePersonality: | |
813 | case ld::Fixup::kindSetTargetAddress: | |
814 | case ld::Fixup::kindSubtractTargetAddress: | |
815 | case ld::Fixup::kindAddAddend: | |
816 | case ld::Fixup::kindSubtractAddend: | |
817 | case ld::Fixup::kindSetTargetImageOffset: | |
818 | case ld::Fixup::kindSetTargetSectionOffset: | |
819 | #if SUPPORT_ARCH_arm64e | |
820 | case ld::Fixup::kindSetAuthData: | |
821 | #endif | |
822 | return false; | |
823 | default: | |
824 | break; | |
825 | } | |
826 | return true; | |
827 | } | |
828 | ||
829 | ||
830 | bool setsTarget(bool isObjectFile) const { | |
831 | switch ( kind ) { | |
832 | case ld::Fixup::kindSetTargetAddress: | |
833 | case ld::Fixup::kindLazyTarget: | |
834 | case ld::Fixup::kindStoreTargetAddressLittleEndian32: | |
835 | case ld::Fixup::kindStoreTargetAddressLittleEndian64: | |
836 | #if SUPPORT_ARCH_arm64e | |
837 | case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: | |
838 | #endif | |
839 | case ld::Fixup::kindStoreTargetAddressBigEndian32: | |
840 | case ld::Fixup::kindStoreTargetAddressBigEndian64: | |
841 | case ld::Fixup::kindStoreTargetAddressX86PCRel32: | |
842 | case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32: | |
843 | case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: | |
844 | case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA: | |
845 | case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad: | |
846 | case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA: | |
847 | case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad: | |
848 | case ld::Fixup::kindStoreTargetAddressARMBranch24: | |
849 | case ld::Fixup::kindStoreTargetAddressThumbBranch22: | |
850 | case ld::Fixup::kindStoreTargetAddressARMLoad12: | |
851 | #if SUPPORT_ARCH_arm64 | |
852 | case ld::Fixup::kindStoreTargetAddressARM64Branch26: | |
853 | case ld::Fixup::kindStoreTargetAddressARM64Page21: | |
854 | case ld::Fixup::kindStoreTargetAddressARM64PageOff12: | |
855 | case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21: | |
856 | case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12: | |
857 | case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21: | |
858 | case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12: | |
859 | case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21: | |
860 | case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12: | |
861 | case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21: | |
862 | case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12: | |
863 | #endif | |
864 | return true; | |
865 | case ld::Fixup::kindStoreX86DtraceCallSiteNop: | |
866 | case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear: | |
867 | case ld::Fixup::kindStoreARMDtraceCallSiteNop: | |
868 | case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear: | |
869 | case ld::Fixup::kindStoreARM64DtraceCallSiteNop: | |
870 | case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear: | |
871 | case ld::Fixup::kindStoreThumbDtraceCallSiteNop: | |
872 | case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear: | |
873 | return isObjectFile; | |
874 | default: | |
875 | break; | |
876 | } | |
877 | return false; | |
878 | } | |
879 | ||
880 | bool isPcRelStore(bool isKextBundle) const { | |
881 | switch ( kind ) { | |
882 | case ld::Fixup::kindStoreX86BranchPCRel8: | |
883 | case ld::Fixup::kindStoreX86BranchPCRel32: | |
884 | case ld::Fixup::kindStoreX86PCRel8: | |
885 | case ld::Fixup::kindStoreX86PCRel16: | |
886 | case ld::Fixup::kindStoreX86PCRel32: | |
887 | case ld::Fixup::kindStoreX86PCRel32_1: | |
888 | case ld::Fixup::kindStoreX86PCRel32_2: | |
889 | case ld::Fixup::kindStoreX86PCRel32_4: | |
890 | case ld::Fixup::kindStoreX86PCRel32GOTLoad: | |
891 | case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA: | |
892 | case ld::Fixup::kindStoreX86PCRel32GOT: | |
893 | case ld::Fixup::kindStoreX86PCRel32TLVLoad: | |
894 | case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA: | |
895 | case ld::Fixup::kindStoreARMBranch24: | |
896 | case ld::Fixup::kindStoreThumbBranch22: | |
897 | case ld::Fixup::kindStoreARMLoad12: | |
898 | case ld::Fixup::kindStoreTargetAddressX86PCRel32: | |
899 | case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: | |
900 | case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA: | |
901 | case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad: | |
902 | case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA: | |
903 | case ld::Fixup::kindStoreTargetAddressARMBranch24: | |
904 | case ld::Fixup::kindStoreTargetAddressThumbBranch22: | |
905 | case ld::Fixup::kindStoreTargetAddressARMLoad12: | |
906 | #if SUPPORT_ARCH_arm64 | |
907 | case ld::Fixup::kindStoreARM64Page21: | |
908 | case ld::Fixup::kindStoreARM64PageOff12: | |
909 | case ld::Fixup::kindStoreARM64GOTLoadPage21: | |
910 | case ld::Fixup::kindStoreARM64GOTLoadPageOff12: | |
911 | case ld::Fixup::kindStoreARM64GOTLeaPage21: | |
912 | case ld::Fixup::kindStoreARM64GOTLeaPageOff12: | |
913 | case ld::Fixup::kindStoreARM64TLVPLoadPage21: | |
914 | case ld::Fixup::kindStoreARM64TLVPLoadPageOff12: | |
915 | case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21: | |
916 | case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12: | |
917 | case ld::Fixup::kindStoreARM64PCRelToGOT: | |
918 | case ld::Fixup::kindStoreTargetAddressARM64Page21: | |
919 | case ld::Fixup::kindStoreTargetAddressARM64PageOff12: | |
920 | case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21: | |
921 | case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12: | |
922 | case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21: | |
923 | case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12: | |
924 | case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21: | |
925 | case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12: | |
926 | case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21: | |
927 | case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12: | |
928 | #endif | |
929 | return true; | |
930 | case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32: | |
931 | #if SUPPORT_ARCH_arm64 | |
932 | case ld::Fixup::kindStoreTargetAddressARM64Branch26: | |
933 | #endif | |
934 | return !isKextBundle; | |
935 | #if SUPPORT_ARCH_arm64 | |
936 | case ld::Fixup::kindStoreARM64Branch26: | |
937 | #endif | |
938 | return !isKextBundle; | |
939 | default: | |
940 | break; | |
941 | } | |
942 | return false; | |
943 | } | |
944 | ||
945 | union LOH_arm64 { | |
946 | uint64_t addend; | |
947 | struct { | |
948 | unsigned kind : 6, | |
949 | count : 2, // 00 => 1 addr, 11 => 4 addrs | |
950 | delta1 : 14, // 16-bit delta, low 2 bits assumed zero | |
951 | delta2 : 14, | |
952 | delta3 : 14, | |
953 | delta4 : 14; | |
954 | } info; | |
955 | }; | |
956 | ||
957 | }; | |
958 | ||
959 | // | |
960 | // ld::Atom | |
961 | // | |
962 | // An atom is the fundamental unit of linking. A C function or global variable is an atom. | |
963 | // An atom has content and attributes. The content of a function atom is the instructions | |
964 | // that implement the function. The content of a global variable atom is its initial bits. | |
965 | // | |
966 | // Name: | |
967 | // The name of an atom is the label name generated by the compiler. A C compiler names foo() | |
968 | // as _foo. A C++ compiler names foo() as __Z3foov. | |
969 | // The name refers to the first byte of the content. An atom cannot have multiple entry points. | |
970 | // Such code is modeled as multiple atoms, each having a "follow on" reference to the next. | |
971 | // A "follow on" reference is a contraint to the linker to the atoms must be laid out contiguously. | |
972 | // | |
973 | // Scope: | |
974 | // An atom is in one of three scopes: translation-unit, linkage-unit, or global. These correspond | |
975 | // to the C visibility of static, hidden, default. | |
976 | // | |
977 | // DefinitionKind: | |
978 | // An atom is one of five defintion kinds: | |
979 | // regular Most atoms. | |
980 | // weak C++ compiler makes some functions weak if there might be multiple copies | |
981 | // that the linker needs to coalesce. | |
982 | // tentative A straggler from ancient C when the extern did not exist. "int foo;" is ambiguous. | |
983 | // It could be a prototype or it could be a definition. | |
984 | // external This is a "proxy" atom produced by a dylib reader. It has no content. It exists | |
985 | // so that the graph of Atoms can be complete. | |
986 | // external-weak Same as external, but the definition in the dylib is weak. | |
987 | // | |
988 | // SymbolTableInclusion: | |
989 | // An atom may or may not be in the symbol table in an object file. | |
990 | // in Most atoms for functions or global data | |
991 | // not-in Anonymous atoms such literal c-strings, or other compiler generated data | |
992 | // not-in-final Atom whose name should not be in the symbol table of final linkd image (e.g. 'l' labels .eh labels) | |
993 | // in-never-strip Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o) | |
994 | // | |
995 | // ContentType: | |
996 | // Some atoms require specially processing by the linker based on their content. For instance, zero-fill data | |
997 | // atom are group together at the end of the DATA segment to reduce disk size. | |
998 | // | |
999 | // ObjectAddress: | |
1000 | // For reproducability, the linker lays out atoms in the order they occurred in the source (object) files. | |
1001 | // The objectAddress() method returns the address of an atom in the object file so that the linker | |
1002 | // can arrange the atoms. | |
1003 | // | |
1004 | // | |
1005 | class Atom | |
1006 | { | |
1007 | public: | |
1008 | enum Scope { scopeTranslationUnit, scopeLinkageUnit, scopeGlobal }; | |
1009 | enum Definition { definitionRegular, definitionTentative, definitionAbsolute, definitionProxy }; | |
1010 | enum Combine { combineNever, combineByName, combineByNameAndContent, combineByNameAndReferences }; | |
1011 | enum ContentType { typeUnclassified, typeZeroFill, typeCString, typeCFI, typeLSDA, typeSectionStart, | |
1012 | typeSectionEnd, typeBranchIsland, typeLazyPointer, typeStub, typeNonLazyPointer, | |
1013 | typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers, | |
1014 | typeLTOtemporary, typeResolver, | |
1015 | typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers, typeTLVPointer }; | |
1016 | ||
1017 | enum SymbolTableInclusion { symbolTableNotIn, symbolTableNotInFinalLinkedImages, symbolTableIn, | |
1018 | symbolTableInAndNeverStrip, symbolTableInAsAbsolute, | |
1019 | symbolTableInWithRandomAutoStripLabel }; | |
1020 | enum WeakImportState { weakImportUnset, weakImportTrue, weakImportFalse }; | |
1021 | ||
1022 | struct Alignment { | |
1023 | Alignment(int p2, int m=0) : powerOf2(p2), modulus(m) {} | |
1024 | uint8_t trailingZeros() const { return (modulus==0) ? powerOf2 : __builtin_ctz(modulus); } | |
1025 | uint16_t powerOf2; | |
1026 | uint16_t modulus; | |
1027 | }; | |
1028 | struct LineInfo { | |
1029 | const char* fileName; | |
1030 | uint32_t atomOffset; | |
1031 | uint32_t lineNumber; | |
1032 | ||
1033 | typedef LineInfo* iterator; | |
1034 | }; | |
1035 | struct UnwindInfo { | |
1036 | uint32_t startOffset; | |
1037 | uint32_t unwindInfo; | |
1038 | ||
1039 | typedef UnwindInfo* iterator; | |
1040 | }; | |
1041 | ||
1042 | Atom(const Section& sect, Definition d, Combine c, Scope s, ContentType ct, | |
1043 | SymbolTableInclusion i, bool dds, bool thumb, bool al, Alignment a) : | |
1044 | _section(§), _address(0), _alignmentModulus(a.modulus), | |
1045 | _alignmentPowerOf2(a.powerOf2), _definition(d), _combine(c), | |
1046 | _dontDeadStrip(dds), _thumb(thumb), _alias(al), _autoHide(false), | |
1047 | _contentType(ct), _symbolTableInclusion(i), | |
1048 | _scope(s), _mode(modeSectionOffset), | |
1049 | _overridesADylibsWeakDef(false), _coalescedAway(false), | |
1050 | _live(false), _dontDeadStripIfRefLive(false), | |
1051 | _machoSection(0), _weakImportState(weakImportUnset) | |
1052 | { | |
1053 | #ifndef NDEBUG | |
1054 | switch ( _combine ) { | |
1055 | case combineByNameAndContent: | |
1056 | case combineByNameAndReferences: | |
1057 | assert(_symbolTableInclusion != symbolTableIn); | |
1058 | assert(_scope != scopeGlobal); | |
1059 | break; | |
1060 | case combineByName: | |
1061 | case combineNever: | |
1062 | break; | |
1063 | }; | |
1064 | #endif | |
1065 | } | |
1066 | virtual ~Atom() {} | |
1067 | ||
1068 | const Section& section() const { return *_section; } | |
1069 | Definition definition() const { return _definition; } | |
1070 | Combine combine() const { return _combine; } | |
1071 | Scope scope() const { return _scope; } | |
1072 | ContentType contentType() const { return _contentType; } | |
1073 | SymbolTableInclusion symbolTableInclusion() const{ return _symbolTableInclusion; } | |
1074 | bool dontDeadStrip() const { return _dontDeadStrip; } | |
1075 | bool dontDeadStripIfReferencesLive() const { return _dontDeadStripIfRefLive; } | |
1076 | bool isThumb() const { return _thumb; } | |
1077 | bool isAlias() const { return _alias; } | |
1078 | Alignment alignment() const { return Alignment(_alignmentPowerOf2, _alignmentModulus); } | |
1079 | bool overridesDylibsWeakDef() const { return _overridesADylibsWeakDef; } | |
1080 | bool coalescedAway() const { return _coalescedAway; } | |
1081 | bool weakImported() const { return _weakImportState == weakImportTrue; } | |
1082 | WeakImportState weakImportState() const { return _weakImportState; } | |
1083 | bool autoHide() const { return _autoHide; } | |
1084 | bool live() const { return _live; } | |
1085 | uint8_t machoSection() const { assert(_machoSection != 0); return _machoSection; } | |
1086 | ||
1087 | void setScope(Scope s) { _scope = s; } | |
1088 | void setSymbolTableInclusion(SymbolTableInclusion i) | |
1089 | { _symbolTableInclusion = i; } | |
1090 | void setCombine(Combine c) { _combine = c; } | |
1091 | void setOverridesDylibsWeakDef() { _overridesADylibsWeakDef = true; } | |
1092 | void setCoalescedAway() { _coalescedAway = true; } | |
1093 | void setWeakImportState(bool w) { assert(_definition == definitionProxy); _weakImportState = ( w ? weakImportTrue : weakImportFalse); } | |
1094 | void setAutoHide() { _autoHide = true; } | |
1095 | void setDontDeadStripIfReferencesLive() { _dontDeadStripIfRefLive = true; } | |
1096 | void setLive() { _live = true; } | |
1097 | void setLive(bool value) { _live = value; } | |
1098 | void setMachoSection(unsigned x) { assert(x != 0); assert(x < 256); _machoSection = x; } | |
1099 | void setSectionOffset(uint64_t o){ assert(_mode == modeSectionOffset); _address = o; _mode = modeSectionOffset; } | |
1100 | void setSectionStartAddress(uint64_t a) { assert(_mode == modeSectionOffset); _address += a; _mode = modeFinalAddress; } | |
1101 | uint64_t sectionOffset() const { assert(_mode == modeSectionOffset); return _address; } | |
1102 | uint64_t finalAddress() const { assert(_mode == modeFinalAddress); return _address; } | |
1103 | #ifndef NDEBUG | |
1104 | bool finalAddressMode() const { return (_mode == modeFinalAddress); } | |
1105 | #endif | |
1106 | virtual const File* file() const = 0; | |
1107 | // Return the original file this atom belongs to, for instance for an LTO atom, | |
1108 | // file() would return the LTO MachO file instead of the original bitcode file. | |
1109 | virtual const ld::File* originalFile() const { return file(); } | |
1110 | virtual const char* translationUnitSource() const { return NULL; } | |
1111 | virtual const char* name() const = 0; | |
1112 | virtual uint64_t objectAddress() const = 0; | |
1113 | virtual uint64_t size() const = 0; | |
1114 | virtual void copyRawContent(uint8_t buffer[]) const = 0; | |
1115 | virtual const uint8_t* rawContentPointer() const { return NULL; } | |
1116 | virtual unsigned long contentHash(const class IndirectBindingTable&) const { return 0; } | |
1117 | virtual bool canCoalesceWith(const Atom& rhs, const class IndirectBindingTable&) const { return false; } | |
1118 | virtual Fixup::iterator fixupsBegin() const { return NULL; } | |
1119 | virtual Fixup::iterator fixupsEnd() const { return NULL; } | |
1120 | bool hasFixupsOfKind(Fixup::Kind kind) const { | |
1121 | for (ld::Fixup::iterator fit = fixupsBegin(), end=fixupsEnd(); fit != end; ++fit) { | |
1122 | if ( fit->kind == kind ) return true; | |
1123 | } | |
1124 | return false; | |
1125 | } | |
1126 | virtual void setFile(const File* f) { } | |
1127 | ||
1128 | virtual UnwindInfo::iterator beginUnwind() const { return NULL; } | |
1129 | virtual UnwindInfo::iterator endUnwind() const { return NULL; } | |
1130 | virtual LineInfo::iterator beginLineInfo() const { return NULL; } | |
1131 | virtual LineInfo::iterator endLineInfo() const { return NULL; } | |
1132 | ||
1133 | void setAttributesFromAtom(const Atom& a) { | |
1134 | _section = a._section; | |
1135 | _alignmentModulus = a._alignmentModulus; | |
1136 | _alignmentPowerOf2 = a._alignmentPowerOf2; | |
1137 | _definition = a._definition; | |
1138 | _combine = a._combine; | |
1139 | _dontDeadStrip = a._dontDeadStrip; | |
1140 | _dontDeadStripIfRefLive = a._dontDeadStripIfRefLive; | |
1141 | _thumb = a._thumb; | |
1142 | _autoHide = a._autoHide; | |
1143 | _contentType = a._contentType; | |
1144 | _symbolTableInclusion = a._symbolTableInclusion; | |
1145 | _scope = a._scope; | |
1146 | _mode = a._mode; | |
1147 | _overridesADylibsWeakDef = a._overridesADylibsWeakDef; | |
1148 | _coalescedAway = a._coalescedAway; | |
1149 | _weakImportState = a._weakImportState; | |
1150 | } | |
1151 | ||
1152 | const char* safeFilePath() const { | |
1153 | const File* f = this->file(); | |
1154 | if ( f != NULL ) | |
1155 | return f->path(); | |
1156 | else | |
1157 | return "<internal>"; | |
1158 | } | |
1159 | ||
1160 | protected: | |
1161 | enum AddressMode { modeSectionOffset, modeFinalAddress }; | |
1162 | ||
1163 | const Section * _section; | |
1164 | uint64_t _address; | |
1165 | uint16_t _alignmentModulus; | |
1166 | uint8_t _alignmentPowerOf2; | |
1167 | Definition _definition : 2; | |
1168 | Combine _combine : 2; | |
1169 | bool _dontDeadStrip : 1; | |
1170 | bool _thumb : 1; | |
1171 | bool _alias : 1; | |
1172 | int _autoHide : 1; | |
1173 | ContentType _contentType : 5; | |
1174 | SymbolTableInclusion _symbolTableInclusion : 3; | |
1175 | Scope _scope : 2; | |
1176 | AddressMode _mode: 2; | |
1177 | bool _overridesADylibsWeakDef : 1; | |
1178 | bool _coalescedAway : 1; | |
1179 | bool _live : 1; | |
1180 | bool _dontDeadStripIfRefLive : 1; | |
1181 | unsigned _machoSection : 8; | |
1182 | WeakImportState _weakImportState : 2; | |
1183 | }; | |
1184 | ||
1185 | ||
1186 | class IndirectBindingTable | |
1187 | { | |
1188 | public: | |
1189 | virtual const char* indirectName(uint32_t bindingIndex) const = 0; | |
1190 | virtual const ld::Atom* indirectAtom(uint32_t bindingIndex) const = 0; | |
1191 | }; | |
1192 | ||
1193 | ||
1194 | ||
1195 | // utility classes for using std::unordered_map with c-strings | |
1196 | struct CStringHash { | |
1197 | size_t operator()(const char* __s) const { | |
1198 | size_t __h = 0; | |
1199 | for ( ; *__s; ++__s) | |
1200 | __h = 5 * __h + *__s; | |
1201 | return __h; | |
1202 | }; | |
1203 | }; | |
1204 | struct CStringEquals | |
1205 | { | |
1206 | bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); } | |
1207 | }; | |
1208 | ||
1209 | typedef std::unordered_set<const char*, ld::CStringHash, ld::CStringEquals> CStringSet; | |
1210 | ||
1211 | ||
1212 | class Internal | |
1213 | { | |
1214 | public: | |
1215 | class FinalSection : public ld::Section { | |
1216 | public: | |
1217 | FinalSection(const Section& sect) : Section(sect), address(0), | |
1218 | fileOffset(0), size(0), alignment(0), | |
1219 | indirectSymTabStartIndex(0), indirectSymTabElementSize(0), | |
1220 | relocStart(0), relocCount(0), | |
1221 | hasLocalRelocs(false), hasExternalRelocs(false) {} | |
1222 | std::vector<const Atom*> atoms; | |
1223 | uint64_t address; | |
1224 | uint64_t fileOffset; | |
1225 | uint64_t size; | |
1226 | uint32_t alignmentPaddingBytes; | |
1227 | uint8_t alignment; | |
1228 | uint32_t indirectSymTabStartIndex; | |
1229 | uint32_t indirectSymTabElementSize; | |
1230 | uint32_t relocStart; | |
1231 | uint32_t relocCount; | |
1232 | bool hasLocalRelocs; | |
1233 | bool hasExternalRelocs; | |
1234 | }; | |
1235 | ||
1236 | typedef std::map<const ld::Atom*, FinalSection*> AtomToSection; | |
1237 | ||
1238 | virtual uint64_t assignFileOffsets() = 0; | |
1239 | virtual void setSectionSizesAndAlignments() = 0; | |
1240 | virtual ld::Internal::FinalSection* addAtom(const Atom&) = 0; | |
1241 | virtual ld::Internal::FinalSection* getFinalSection(const ld::Section& inputSection) = 0; | |
1242 | virtual ~Internal() {} | |
1243 | Internal() : bundleLoader(NULL), | |
1244 | entryPoint(NULL), classicBindingHelper(NULL), | |
1245 | lazyBindingHelper(NULL), compressedFastBinderProxy(NULL), | |
1246 | hasObjC(false), | |
1247 | swiftVersion(0), cpuSubType(0), minOSVersion(0), | |
1248 | objectFileFoundWithNoVersion(false), | |
1249 | allObjectFilesScatterable(true), | |
1250 | someObjectFileHasDwarf(false), usingHugeSections(false), | |
1251 | someObjectFileHasSwift(false), firstSwiftDylibFile(nullptr), | |
1252 | hasThreadLocalVariableDefinitions(false), | |
1253 | hasWeakExternalSymbols(false), | |
1254 | someObjectHasOptimizationHints(false), | |
1255 | dropAllBitcode(false), embedMarkerOnly(false), | |
1256 | forceLoadCompilerRT(false) { } | |
1257 | ||
1258 | std::vector<FinalSection*> sections; | |
1259 | std::vector<ld::dylib::File*> dylibs; | |
1260 | std::vector<std::string> archivePaths; | |
1261 | std::vector<ld::relocatable::File::Stab> stabs; | |
1262 | AtomToSection atomToSection; | |
1263 | CStringSet unprocessedLinkerOptionLibraries; | |
1264 | CStringSet unprocessedLinkerOptionFrameworks; | |
1265 | CStringSet linkerOptionLibraries; | |
1266 | CStringSet linkerOptionFrameworks; | |
1267 | CStringSet missingLinkerOptionLibraries; | |
1268 | CStringSet missingLinkerOptionFrameworks; | |
1269 | std::vector<const ld::Atom*> indirectBindingTable; | |
1270 | std::vector<const ld::relocatable::File*> filesWithBitcode; | |
1271 | std::vector<const ld::relocatable::File*> filesFromCompilerRT; | |
1272 | std::vector<const ld::Atom*> deadAtoms; | |
1273 | std::unordered_set<const char*> allUndefProxies; | |
1274 | std::unordered_set<uint64_t> toolsVersions; | |
1275 | const ld::dylib::File* bundleLoader; | |
1276 | const Atom* entryPoint; | |
1277 | const Atom* classicBindingHelper; | |
1278 | const Atom* lazyBindingHelper; | |
1279 | const Atom* compressedFastBinderProxy; | |
1280 | bool hasObjC; | |
1281 | uint8_t swiftVersion; | |
1282 | uint32_t cpuSubType; | |
1283 | uint32_t minOSVersion; | |
1284 | VersionSet derivedPlatforms; | |
1285 | bool objectFileFoundWithNoVersion; | |
1286 | bool allObjectFilesScatterable; | |
1287 | bool someObjectFileHasDwarf; | |
1288 | bool usingHugeSections; | |
1289 | bool someObjectFileHasSwift; | |
1290 | const ld::dylib::File* firstSwiftDylibFile; | |
1291 | bool hasThreadLocalVariableDefinitions; | |
1292 | bool hasWeakExternalSymbols; | |
1293 | bool someObjectHasOptimizationHints; | |
1294 | bool dropAllBitcode; | |
1295 | bool embedMarkerOnly; | |
1296 | bool forceLoadCompilerRT; | |
1297 | std::vector<std::string> ltoBitcodePath; | |
1298 | }; | |
1299 | ||
1300 | ||
1301 | ||
1302 | ||
1303 | ||
1304 | ||
1305 | ||
1306 | } // namespace ld | |
1307 | ||
1308 | #endif // __LD_HPP__ |