]>
Commit | Line | Data |
---|---|---|
a645023d A |
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 | ||
eaf282aa A |
34 | #include <set> |
35 | #include <map> | |
a645023d | 36 | #include <vector> |
eaf282aa | 37 | #include <string> |
f80fe69f | 38 | #include <unordered_set> |
a645023d | 39 | |
f80fe69f | 40 | #include "configure.h" |
a645023d A |
41 | |
42 | namespace ld { | |
43 | ||
eaf282aa A |
44 | // Forward declaration for bitcode support |
45 | class Bitcode; | |
46 | ||
a645023d A |
47 | // |
48 | // ld::File | |
49 | // | |
50 | // Abstract base class for all object or library files the linker processes. | |
51 | // | |
52 | // forEachAtom() iterates over the Atoms in the order they occur in the file. | |
53 | // | |
54 | // justInTimeforEachAtom(name) iterates over lazily created Atoms. For instance if | |
55 | // File is a static library, justInTimeforEachAtom() will iterate over the base set | |
56 | // of Atoms from the archive member implementing 'name'. | |
57 | // | |
58 | class File | |
59 | { | |
60 | public: | |
f80fe69f A |
61 | enum ObjcConstraint { objcConstraintNone, objcConstraintRetainRelease, |
62 | objcConstraintRetainReleaseOrGC, objcConstraintGC, | |
63 | objcConstraintRetainReleaseForSimulator }; | |
a645023d A |
64 | |
65 | class AtomHandler { | |
66 | public: | |
67 | virtual ~AtomHandler() {} | |
68 | virtual void doAtom(const class Atom&) = 0; | |
69 | virtual void doFile(const class File&) = 0; | |
70 | }; | |
71 | ||
ebf6f434 A |
72 | // |
73 | // ld::File::Ordinal | |
74 | // | |
75 | // Codifies the rules of ordering input files for symbol precedence. These are: | |
76 | // - Input files listed on the command line are ordered according to their index in the argument list. | |
77 | // - Input files listed in a file list are ordered first at the index of the file list argument, then | |
78 | // by index in the file list | |
79 | // - Input files extracted from archives are ordered using the ordinal of the archive itself plus the | |
80 | // index of the object file within the archive | |
81 | // - Indirect dylibs are ordered after all input files derived from the command line, in the order that | |
82 | // they are discovered. | |
83 | // - The LTO object file is last. | |
84 | // | |
85 | class Ordinal | |
86 | { | |
87 | private: | |
88 | // The actual numeric ordinal. Lower values have higher precedence and a zero value is invalid. | |
89 | // The 64 bit ordinal is broken into 4 16 bit chunks. The high 16 bits are a "partition" that | |
90 | // is used to distinguish major ordinal groups: command line, indirect dylib, LTO. | |
91 | // The remaining chunks are used according to the partition (see below). | |
92 | uint64_t _ordinal; | |
93 | ||
94 | Ordinal (uint64_t ordinal) : _ordinal(ordinal) {} | |
95 | ||
0a8dc3df | 96 | enum { kArgListPartition=0, kIndirectDylibPartition=1, kLTOPartition = 2, kLinkerOptionPartition = 3, InvalidParition=0xffff }; |
ebf6f434 A |
97 | Ordinal(uint16_t partition, uint16_t majorIndex, uint16_t minorIndex, uint16_t counter) { |
98 | _ordinal = ((uint64_t)partition<<48) | ((uint64_t)majorIndex<<32) | ((uint64_t)minorIndex<<16) | ((uint64_t)counter<<0); | |
99 | } | |
100 | ||
101 | const uint16_t partition() const { return (_ordinal>>48)&0xffff; } | |
102 | const uint16_t majorIndex() const { return (_ordinal>>32)&0xffff; } | |
103 | const uint16_t minorIndex() const { return (_ordinal>>16)&0xffff; } | |
104 | const uint16_t counter() const { return (_ordinal>>00)&0xffff; } | |
0a8dc3df | 105 | |
ebf6f434 A |
106 | const Ordinal nextMajorIndex() const { assert(majorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<32)); } |
107 | const Ordinal nextMinorIndex() const { assert(minorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<16)); } | |
108 | const Ordinal nextCounter() const { assert(counter() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<0)); } | |
109 | ||
110 | public: | |
111 | Ordinal() : _ordinal(0) {}; | |
0a8dc3df | 112 | |
ebf6f434 A |
113 | static const Ordinal NullOrdinal() { return Ordinal((uint64_t)0); } |
114 | ||
115 | const bool validOrdinal() const { return _ordinal != 0; } | |
116 | ||
117 | bool operator ==(const Ordinal& rhs) const { return _ordinal == rhs._ordinal; } | |
118 | bool operator !=(const Ordinal& rhs) const { return _ordinal != rhs._ordinal; } | |
119 | bool operator < (const Ordinal& rhs) const { return _ordinal < rhs._ordinal; } | |
120 | bool operator > (const Ordinal& rhs) const { return _ordinal > rhs._ordinal; } | |
121 | ||
122 | // For ordinals derived from the command line args the partition is ArgListPartition | |
123 | // The majorIndex is the arg index that pulls in the file, file list, or archive. | |
124 | // 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. | |
125 | // The counter is used for .a files and the value is the index of the object in the archive. | |
126 | // Thus, an object pulled in from a .a that was listed in a file list could use all three fields. | |
f80fe69f | 127 | static const Ordinal makeArgOrdinal(uint16_t argIndex) { return Ordinal(kArgListPartition, argIndex, 0, 0); }; |
ebf6f434 | 128 | const Ordinal nextFileListOrdinal() const { return nextMinorIndex(); } |
0a8dc3df | 129 | const Ordinal archiveOrdinalWithMemberIndex(uint16_t memberIndex) const { return Ordinal(partition(), majorIndex(), minorIndex(), memberIndex); } |
ebf6f434 A |
130 | |
131 | // For indirect libraries the partition is IndirectDylibPartition and the counter is used or order the libraries. | |
f80fe69f | 132 | static const ld::File::Ordinal indirectDylibBase() { return Ordinal(kIndirectDylibPartition, 0, 0, 0); } |
ebf6f434 A |
133 | const Ordinal nextIndirectDylibOrdinal() const { return nextCounter(); } |
134 | ||
135 | // For the LTO mach-o the partition is LTOPartition. As there is only one LTO file no other fields are needed. | |
f80fe69f A |
136 | static const ld::File::Ordinal LTOOrdinal() { return Ordinal(kLTOPartition, 0, 0, 0); } |
137 | ||
138 | // For linker options embedded in object files | |
139 | static const ld::File::Ordinal linkeOptionBase() { return Ordinal(kIndirectDylibPartition, 1, 0, 0); } | |
0a8dc3df A |
140 | const Ordinal nextLinkerOptionOrdinal() { return nextCounter(); }; |
141 | ||
ebf6f434 A |
142 | }; |
143 | ||
144 | typedef enum { Reloc, Dylib, Archive, Other } Type; | |
145 | ||
146 | File(const char* pth, time_t modTime, Ordinal ord, Type type) | |
147 | : _path(pth), _modTime(modTime), _ordinal(ord), _type(type) { } | |
a645023d A |
148 | virtual ~File() {} |
149 | const char* path() const { return _path; } | |
150 | time_t modificationTime() const{ return _modTime; } | |
ebf6f434 | 151 | Ordinal ordinal() const { return _ordinal; } |
a645023d A |
152 | virtual bool forEachAtom(AtomHandler&) const = 0; |
153 | virtual bool justInTimeforEachAtom(const char* name, AtomHandler&) const = 0; | |
154 | virtual ObjcConstraint objCConstraint() const { return objcConstraintNone; } | |
0a8dc3df | 155 | virtual bool objcHasCategoryClassPropertiesField() const { return false; } |
599556ff | 156 | virtual uint8_t swiftVersion() const { return 0; } |
a645023d A |
157 | virtual uint32_t cpuSubType() const { return 0; } |
158 | virtual uint32_t subFileCount() const { return 1; } | |
eaf282aa | 159 | virtual uint32_t minOSVersion() const { return 0; } |
bee7e226 | 160 | virtual uint32_t platform() const { return 0; } |
ebf6f434 A |
161 | bool fileExists() const { return _modTime != 0; } |
162 | Type type() const { return _type; } | |
eaf282aa | 163 | virtual Bitcode* getBitcode() const { return NULL; } |
a645023d A |
164 | private: |
165 | const char* _path; | |
166 | time_t _modTime; | |
ebf6f434 A |
167 | const Ordinal _ordinal; |
168 | const Type _type; | |
a645023d A |
169 | }; |
170 | ||
171 | ||
172 | // | |
173 | // minumum OS versions | |
174 | // | |
175 | enum MacVersionMin { macVersionUnset=0, mac10_4=0x000A0400, mac10_5=0x000A0500, | |
ebf6f434 | 176 | mac10_6=0x000A0600, mac10_7=0x000A0700, mac10_8=0x000A0800, |
0a8dc3df | 177 | mac10_9=0x000A0900, mac10_12=0x000A0C00, mac10_Future=0x10000000 }; |
afe874b1 | 178 | enum IOSVersionMin { iOSVersionUnset=0, iOS_2_0=0x00020000, iOS_3_1=0x00030100, |
ebf6f434 | 179 | iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000, |
599556ff | 180 | iOS_6_0=0x00060000, iOS_7_0=0x00070000, iOS_8_0=0x00080000, |
0a8dc3df | 181 | iOS_9_0=0x00090000, iOS_10_0=0x000A0000, iOS_Future=0x10000000}; |
eaf282aa A |
182 | enum WatchOSVersionMin { wOSVersionUnset=0, wOS_1_0=0x00010000, wOS_2_0=0x00020000 }; |
183 | ||
184 | ||
a645023d A |
185 | namespace relocatable { |
186 | // | |
187 | // ld::relocatable::File | |
188 | // | |
189 | // Abstract base class for object files the linker processes. | |
190 | // | |
a645023d A |
191 | // debugInfo() returns if the object file contains debugger information (stabs or dwarf). |
192 | // | |
193 | // stabs() lazily creates a vector of Stab objects for each atom | |
194 | // | |
195 | // canScatterAtoms() true for all compiler generated code. Hand written assembly can opt-in | |
196 | // via .subsections_via_symbols directive. When true it means the linker can break up section | |
197 | // content at symbol boundaries and do optimizations like coalescing, dead code stripping, or | |
198 | // apply order files. | |
199 | // | |
200 | // optimize() used by libLTO to lazily generate code from llvm bit-code files | |
201 | // | |
202 | class File : public ld::File | |
203 | { | |
204 | public: | |
205 | enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 }; | |
dd9e569f | 206 | enum SourceKind { kSourceUnknown=0, kSourceObj, kSourceLTO, kSourceArchive, kSourceCompilerArchive }; |
a645023d A |
207 | struct Stab { |
208 | const class Atom* atom; | |
209 | uint8_t type; | |
210 | uint8_t other; | |
211 | uint16_t desc; | |
212 | uint32_t value; | |
213 | const char* string; | |
214 | }; | |
f80fe69f | 215 | typedef const std::vector< std::vector<const char*> > LinkerOptionsList; |
bee7e226 | 216 | typedef std::vector<std::pair<uint32_t,uint32_t>> ToolVersionList; |
a645023d | 217 | |
ebf6f434 A |
218 | File(const char* pth, time_t modTime, Ordinal ord) |
219 | : ld::File(pth, modTime, ord, Reloc) { } | |
a645023d | 220 | virtual ~File() {} |
a645023d A |
221 | virtual DebugInfoKind debugInfo() const = 0; |
222 | virtual const char* debugInfoPath() const { return path(); } | |
223 | virtual time_t debugInfoModificationTime() const { return modificationTime(); } | |
224 | virtual const std::vector<Stab>* stabs() const = 0; | |
225 | virtual bool canScatterAtoms() const = 0; | |
226 | virtual bool hasLongBranchStubs() { return false; } | |
f80fe69f | 227 | virtual LinkerOptionsList* linkerOptions() const = 0; |
bee7e226 | 228 | virtual const ToolVersionList& toolVersions() const = 0; |
eaf282aa | 229 | virtual SourceKind sourceKind() const { return kSourceUnknown; } |
82b4b32b | 230 | virtual const uint8_t* fileContent() const { return nullptr; } |
a645023d A |
231 | }; |
232 | } // namespace relocatable | |
233 | ||
234 | ||
235 | namespace dylib { | |
236 | ||
237 | // | |
238 | // ld::dylib::File | |
239 | // | |
240 | // Abstract base class for dynamic shared libraries read by the linker processes. | |
241 | // | |
242 | class File : public ld::File | |
243 | { | |
244 | public: | |
245 | class DylibHandler | |
246 | { | |
247 | public: | |
248 | virtual ~DylibHandler() {} | |
0a8dc3df | 249 | virtual File* findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative) = 0; |
a645023d A |
250 | }; |
251 | ||
ebf6f434 | 252 | File(const char* pth, time_t modTime, Ordinal ord) |
ec29ba20 | 253 | : ld::File(pth, modTime, ord, Dylib), _dylibInstallPath(NULL), _frameworkName(NULL), |
a645023d | 254 | _dylibTimeStamp(0), _dylibCurrentVersion(0), _dylibCompatibilityVersion(0), |
0a8dc3df | 255 | _explicitlyLinked(false), _implicitlyLinked(false), _speculativelyLoaded(false), |
afe874b1 A |
256 | _lazyLoadedDylib(false), _forcedWeakLinked(false), _reExported(false), |
257 | _upward(false), _dead(false) { } | |
a645023d | 258 | const char* installPath() const { return _dylibInstallPath; } |
ec29ba20 | 259 | const char* frameworkName() const { return _frameworkName; } |
a645023d A |
260 | uint32_t timestamp() const { return _dylibTimeStamp; } |
261 | uint32_t currentVersion() const { return _dylibCurrentVersion; } | |
262 | uint32_t compatibilityVersion() const{ return _dylibCompatibilityVersion; } | |
263 | void setExplicitlyLinked() { _explicitlyLinked = true; } | |
264 | bool explicitlyLinked() const { return _explicitlyLinked; } | |
265 | void setImplicitlyLinked() { _implicitlyLinked = true; } | |
266 | bool implicitlyLinked() const { return _implicitlyLinked; } | |
0a8dc3df A |
267 | void setSpeculativelyLoaded() { _speculativelyLoaded = true; } |
268 | bool speculativelyLoaded() const { return _speculativelyLoaded; } | |
269 | ||
a645023d A |
270 | // attributes of how dylib will be used when linked |
271 | void setWillBeLazyLoadedDylb() { _lazyLoadedDylib = true; } | |
272 | bool willBeLazyLoadedDylib() const { return _lazyLoadedDylib; } | |
afe874b1 A |
273 | void setForcedWeakLinked() { _forcedWeakLinked = true; } |
274 | bool forcedWeakLinked() const { return _forcedWeakLinked; } | |
275 | ||
a645023d A |
276 | void setWillBeReExported() { _reExported = true; } |
277 | bool willBeReExported() const { return _reExported; } | |
278 | void setWillBeUpwardDylib() { _upward = true; } | |
279 | bool willBeUpwardDylib() const { return _upward; } | |
a645023d A |
280 | void setWillBeRemoved(bool value) { _dead = value; } |
281 | bool willRemoved() const { return _dead; } | |
282 | ||
283 | virtual void processIndirectLibraries(DylibHandler* handler, bool addImplicitDylibs) = 0; | |
284 | virtual bool providedExportAtom() const = 0; | |
285 | virtual const char* parentUmbrella() const = 0; | |
286 | virtual const std::vector<const char*>* allowableClients() const = 0; | |
0a8dc3df | 287 | virtual const std::vector<const char*>& rpaths() const = 0; |
a645023d A |
288 | virtual bool hasWeakExternals() const = 0; |
289 | virtual bool deadStrippable() const = 0; | |
290 | virtual bool hasWeakDefinition(const char* name) const = 0; | |
291 | virtual bool hasPublicInstallName() const = 0; | |
afe874b1 | 292 | virtual bool allSymbolsAreWeakImported() const = 0; |
f80fe69f | 293 | virtual bool installPathVersionSpecific() const { return false; } |
599556ff | 294 | virtual bool appExtensionSafe() const = 0; |
599556ff | 295 | |
ec29ba20 | 296 | public: |
a645023d | 297 | const char* _dylibInstallPath; |
ec29ba20 | 298 | const char* _frameworkName; |
a645023d A |
299 | uint32_t _dylibTimeStamp; |
300 | uint32_t _dylibCurrentVersion; | |
301 | uint32_t _dylibCompatibilityVersion; | |
302 | bool _explicitlyLinked; | |
303 | bool _implicitlyLinked; | |
0a8dc3df | 304 | bool _speculativelyLoaded; |
a645023d | 305 | bool _lazyLoadedDylib; |
afe874b1 | 306 | bool _forcedWeakLinked; |
a645023d A |
307 | bool _reExported; |
308 | bool _upward; | |
a645023d A |
309 | bool _dead; |
310 | }; | |
311 | } // namespace dylib | |
312 | ||
313 | ||
afe874b1 A |
314 | namespace archive { |
315 | // | |
316 | // ld::archive::File | |
317 | // | |
318 | // Abstract base class for static libraries read by the linker processes. | |
319 | // | |
320 | class File : public ld::File | |
321 | { | |
322 | public: | |
ebf6f434 A |
323 | File(const char* pth, time_t modTime, Ordinal ord) |
324 | : ld::File(pth, modTime, ord, Archive) { } | |
afe874b1 A |
325 | virtual ~File() {} |
326 | virtual bool justInTimeDataOnlyforEachAtom(const char* name, AtomHandler&) const = 0; | |
327 | }; | |
328 | } // namespace archive | |
329 | ||
a645023d A |
330 | |
331 | // | |
332 | // ld::Section | |
333 | // | |
334 | class Section | |
335 | { | |
336 | public: | |
337 | enum Type { typeUnclassified, typeCode, typePageZero, typeImportProxies, typeLinkEdit, typeMachHeader, typeStack, | |
599556ff | 338 | typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO, typeTempAlias, |
a645023d A |
339 | typeCString, typeNonStdCString, typeCStringPointer, typeUTF16Strings, typeCFString, typeObjC1Classes, |
340 | typeCFI, typeLSDA, typeDtraceDOF, typeUnwindInfo, typeObjCClassRefs, typeObjC2CategoryList, | |
341 | typeZeroFill, typeTentativeDefs, typeLazyPointer, typeStub, typeNonLazyPointer, typeDyldInfo, | |
342 | typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers, | |
343 | typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols, | |
344 | typeTLVDefs, typeTLVZeroFill, typeTLVInitialValues, typeTLVInitializerPointers, typeTLVPointers, | |
eaf282aa | 345 | typeFirstSection, typeLastSection, typeDebug, typeSectCreate }; |
a645023d A |
346 | |
347 | ||
348 | Section(const char* sgName, const char* sctName, | |
349 | Type t, bool hidden=false) | |
350 | : _segmentName(sgName), _sectionName(sctName), | |
351 | _type(t), _hidden(hidden) {} | |
352 | Section(const Section& sect) | |
353 | : _segmentName(sect.segmentName()), _sectionName(sect.sectionName()), | |
354 | _type(sect.type()), _hidden(sect.isSectionHidden()) {} | |
355 | ||
356 | bool operator==(const Section& rhs) const { return ( (_hidden==rhs._hidden) && | |
357 | (strcmp(_segmentName, rhs._segmentName)==0) && | |
358 | (strcmp(_sectionName, rhs._sectionName)==0) ); } | |
359 | bool operator!=(const Section& rhs) const { return ! (*this == rhs); } | |
360 | const char* segmentName() const { return _segmentName; } | |
361 | const char* sectionName() const { return _sectionName; } | |
362 | Type type() const { return _type; } | |
363 | bool isSectionHidden() const { return _hidden; } | |
364 | ||
365 | private: | |
366 | const char* _segmentName; | |
367 | const char* _sectionName; | |
368 | Type _type; | |
369 | bool _hidden; | |
370 | }; | |
371 | ||
372 | ||
373 | ||
374 | // | |
375 | // ld::Fixup | |
376 | // | |
377 | // A Fixup describes how part of an Atom's content must be fixed up. For instance, | |
378 | // an instruction may contain a displacement to another Atom that must be | |
379 | // fixed up by the linker. | |
380 | // | |
381 | // A Fixup my reference another Atom. There are two kinds of references: direct and by-name. | |
382 | // With a direct reference, the target is bound by the File that created it. | |
383 | // For instance a reference to a static would produce a direct reference. | |
384 | // A by-name reference requires the linker to find the target Atom with the | |
385 | // required name in order to be bound. | |
386 | // | |
387 | // For a link to succeed all Fixup must be bound. | |
388 | // | |
389 | // A Reference also has a fix-up-offset. This is the offset into the content of the | |
390 | // Atom holding the reference where the fix-up (relocation) will be applied. | |
391 | // | |
392 | // | |
393 | struct Fixup | |
394 | { | |
395 | enum TargetBinding { bindingNone, bindingByNameUnbound, bindingDirectlyBound, bindingByContentBound, bindingsIndirectlyBound }; | |
396 | enum Cluster { k1of1, k1of2, k2of2, k1of3, k2of3, k3of3, k1of4, k2of4, k3of4, k4of4, k1of5, k2of5, k3of5, k4of5, k5of5 }; | |
397 | enum Kind { kindNone, kindNoneFollowOn, | |
398 | // grouping | |
399 | kindNoneGroupSubordinate, | |
400 | kindNoneGroupSubordinateFDE, kindNoneGroupSubordinateLSDA, kindNoneGroupSubordinatePersonality, | |
401 | // value calculations | |
402 | kindSetTargetAddress, | |
403 | kindSubtractTargetAddress, | |
404 | kindAddAddend, | |
405 | kindSubtractAddend, | |
406 | kindSetTargetImageOffset, | |
407 | kindSetTargetSectionOffset, | |
408 | kindSetTargetTLVTemplateOffset, | |
409 | // pointer store kinds (of current calculated value) | |
410 | kindStore8, | |
411 | kindStoreLittleEndian16, | |
412 | kindStoreLittleEndianLow24of32, | |
413 | kindStoreLittleEndian32, | |
414 | kindStoreLittleEndian64, | |
415 | kindStoreBigEndian16, | |
416 | kindStoreBigEndianLow24of32, | |
417 | kindStoreBigEndian32, | |
418 | kindStoreBigEndian64, | |
419 | // Intel specific store kinds | |
420 | kindStoreX86BranchPCRel8, kindStoreX86BranchPCRel32, | |
421 | kindStoreX86PCRel8, kindStoreX86PCRel16, | |
422 | kindStoreX86PCRel32, kindStoreX86PCRel32_1, kindStoreX86PCRel32_2, kindStoreX86PCRel32_4, | |
423 | kindStoreX86PCRel32GOTLoad, kindStoreX86PCRel32GOTLoadNowLEA, kindStoreX86PCRel32GOT, | |
424 | kindStoreX86PCRel32TLVLoad, kindStoreX86PCRel32TLVLoadNowLEA, | |
425 | kindStoreX86Abs32TLVLoad, kindStoreX86Abs32TLVLoadNowLEA, | |
426 | // ARM specific store kinds | |
427 | kindStoreARMBranch24, kindStoreThumbBranch22, | |
428 | kindStoreARMLoad12, | |
429 | kindStoreARMLow16, kindStoreARMHigh16, | |
430 | kindStoreThumbLow16, kindStoreThumbHigh16, | |
f80fe69f A |
431 | #if SUPPORT_ARCH_arm64 |
432 | // ARM64 specific store kinds | |
433 | kindStoreARM64Branch26, | |
434 | kindStoreARM64Page21, kindStoreARM64PageOff12, | |
435 | kindStoreARM64GOTLoadPage21, kindStoreARM64GOTLoadPageOff12, | |
436 | kindStoreARM64GOTLeaPage21, kindStoreARM64GOTLeaPageOff12, | |
437 | kindStoreARM64TLVPLoadPage21, kindStoreARM64TLVPLoadPageOff12, | |
9543cb2f | 438 | kindStoreARM64TLVPLoadNowLeaPage21, kindStoreARM64TLVPLoadNowLeaPageOff12, |
f80fe69f A |
439 | kindStoreARM64PointerToGOT, kindStoreARM64PCRelToGOT, |
440 | #endif | |
a645023d A |
441 | // dtrace probes |
442 | kindDtraceExtra, | |
443 | kindStoreX86DtraceCallSiteNop, kindStoreX86DtraceIsEnableSiteClear, | |
444 | kindStoreARMDtraceCallSiteNop, kindStoreARMDtraceIsEnableSiteClear, | |
f80fe69f | 445 | kindStoreARM64DtraceCallSiteNop, kindStoreARM64DtraceIsEnableSiteClear, |
a645023d | 446 | kindStoreThumbDtraceCallSiteNop, kindStoreThumbDtraceIsEnableSiteClear, |
a645023d A |
447 | // lazy binding |
448 | kindLazyTarget, kindSetLazyOffset, | |
9543cb2f A |
449 | // islands |
450 | kindIslandTarget, | |
ebf6f434 A |
451 | // data-in-code markers |
452 | kindDataInCodeStartData, kindDataInCodeStartJT8, kindDataInCodeStartJT16, | |
453 | kindDataInCodeStartJT32, kindDataInCodeStartJTA32, kindDataInCodeEnd, | |
ec29ba20 | 454 | // linker optimization hints |
9543cb2f | 455 | kindLinkerOptimizationHint, |
a645023d A |
456 | // pointer store combinations |
457 | kindStoreTargetAddressLittleEndian32, // kindSetTargetAddress + kindStoreLittleEndian32 | |
458 | kindStoreTargetAddressLittleEndian64, // kindSetTargetAddress + kindStoreLittleEndian64 | |
459 | kindStoreTargetAddressBigEndian32, // kindSetTargetAddress + kindStoreBigEndian32 | |
460 | kindStoreTargetAddressBigEndian64, // kindSetTargetAddress + kindStoreBigEndian364 | |
461 | kindSetTargetTLVTemplateOffsetLittleEndian32, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian32 | |
462 | kindSetTargetTLVTemplateOffsetLittleEndian64, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian64 | |
463 | // Intel value calculation and store combinations | |
464 | kindStoreTargetAddressX86PCRel32, // kindSetTargetAddress + kindStoreX86PCRel32 | |
465 | kindStoreTargetAddressX86BranchPCRel32, // kindSetTargetAddress + kindStoreX86BranchPCRel32 | |
466 | kindStoreTargetAddressX86PCRel32GOTLoad,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoad | |
467 | kindStoreTargetAddressX86PCRel32GOTLoadNowLEA,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoadNowLEA | |
468 | kindStoreTargetAddressX86PCRel32TLVLoad, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoad | |
469 | kindStoreTargetAddressX86PCRel32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoadNowLEA | |
470 | kindStoreTargetAddressX86Abs32TLVLoad, // kindSetTargetAddress + kindStoreX86Abs32TLVLoad | |
471 | kindStoreTargetAddressX86Abs32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86Abs32TLVLoadNowLEA | |
472 | // ARM value calculation and store combinations | |
473 | kindStoreTargetAddressARMBranch24, // kindSetTargetAddress + kindStoreARMBranch24 | |
474 | kindStoreTargetAddressThumbBranch22, // kindSetTargetAddress + kindStoreThumbBranch22 | |
475 | kindStoreTargetAddressARMLoad12, // kindSetTargetAddress + kindStoreARMLoad12 | |
f80fe69f A |
476 | #if SUPPORT_ARCH_arm64 |
477 | // ARM64 value calculation and store combinations | |
478 | kindStoreTargetAddressARM64Branch26, // kindSetTargetAddress + kindStoreARM64Branch26 | |
479 | kindStoreTargetAddressARM64Page21, // kindSetTargetAddress + kindStoreARM64Page21 | |
480 | kindStoreTargetAddressARM64PageOff12, // kindSetTargetAddress + kindStoreARM64PageOff12 | |
481 | kindStoreTargetAddressARM64GOTLoadPage21, // kindSetTargetAddress + kindStoreARM64GOTLoadPage21 | |
482 | kindStoreTargetAddressARM64GOTLoadPageOff12,// kindSetTargetAddress + kindStoreARM64GOTLoadPageOff12 | |
483 | kindStoreTargetAddressARM64GOTLeaPage21, // kindSetTargetAddress + kindStoreARM64GOTLeaPage21 | |
484 | kindStoreTargetAddressARM64GOTLeaPageOff12, // kindSetTargetAddress + kindStoreARM64GOTLeaPageOff12 | |
9543cb2f A |
485 | kindStoreTargetAddressARM64TLVPLoadPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadPage21 |
486 | kindStoreTargetAddressARM64TLVPLoadPageOff12,// kindSetTargetAddress + kindStoreARM64TLVPLoadPageOff12 | |
487 | kindStoreTargetAddressARM64TLVPLoadNowLeaPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPage21 | |
488 | kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPageOff12 | |
f80fe69f | 489 | #endif |
a645023d A |
490 | }; |
491 | ||
492 | union { | |
493 | const Atom* target; | |
494 | const char* name; | |
495 | uint64_t addend; | |
496 | uint32_t bindingIndex; | |
497 | } u; | |
498 | uint32_t offsetInAtom; | |
499 | Kind kind : 8; | |
500 | Cluster clusterSize : 4; | |
501 | bool weakImport : 1; | |
502 | TargetBinding binding : 3; | |
503 | bool contentAddendOnly : 1; | |
504 | bool contentDetlaToAddendOnly : 1; | |
f80fe69f | 505 | bool contentIgnoresAddend : 1; |
a645023d A |
506 | |
507 | typedef Fixup* iterator; | |
508 | ||
509 | Fixup() : | |
510 | offsetInAtom(0), kind(kindNone), clusterSize(k1of1), weakImport(false), | |
511 | binding(bindingNone), | |
f80fe69f | 512 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) { u.target = NULL; } |
a645023d A |
513 | |
514 | Fixup(Kind k, Atom* targetAtom) : | |
515 | offsetInAtom(0), kind(k), clusterSize(k1of1), weakImport(false), | |
516 | binding(Fixup::bindingDirectlyBound), | |
f80fe69f | 517 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) |
a645023d A |
518 | { assert(targetAtom != NULL); u.target = targetAtom; } |
519 | ||
520 | Fixup(uint32_t off, Cluster c, Kind k) : | |
521 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), | |
522 | binding(Fixup::bindingNone), | |
f80fe69f | 523 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) |
a645023d A |
524 | { u.addend = 0; } |
525 | ||
526 | Fixup(uint32_t off, Cluster c, Kind k, bool weakIm, const char* name) : | |
527 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(weakIm), | |
528 | binding(Fixup::bindingByNameUnbound), | |
f80fe69f | 529 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) |
a645023d A |
530 | { assert(name != NULL); u.name = name; } |
531 | ||
532 | Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const char* name) : | |
533 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b), | |
f80fe69f | 534 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) |
a645023d A |
535 | { assert(name != NULL); u.name = name; } |
536 | ||
537 | Fixup(uint32_t off, Cluster c, Kind k, const Atom* targetAtom) : | |
538 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), | |
539 | binding(Fixup::bindingDirectlyBound), | |
f80fe69f | 540 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) |
a645023d A |
541 | { assert(targetAtom != NULL); u.target = targetAtom; } |
542 | ||
543 | Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const Atom* targetAtom) : | |
544 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b), | |
f80fe69f | 545 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) |
a645023d A |
546 | { assert(targetAtom != NULL); u.target = targetAtom; } |
547 | ||
548 | Fixup(uint32_t off, Cluster c, Kind k, uint64_t addend) : | |
549 | offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), | |
550 | binding(Fixup::bindingNone), | |
f80fe69f | 551 | contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) |
a645023d A |
552 | { u.addend = addend; } |
553 | ||
9543cb2f A |
554 | Fixup(Kind k, uint32_t lohKind, uint32_t off1, uint32_t off2) : |
555 | offsetInAtom(off1), kind(k), clusterSize(k1of1), | |
556 | weakImport(false), binding(Fixup::bindingNone), contentAddendOnly(false), | |
557 | contentDetlaToAddendOnly(false), contentIgnoresAddend(false) { | |
558 | assert(k == kindLinkerOptimizationHint); | |
559 | LOH_arm64 extra; | |
560 | extra.addend = 0; | |
561 | extra.info.kind = lohKind; | |
562 | extra.info.count = 1; | |
563 | extra.info.delta1 = 0; | |
564 | extra.info.delta2 = (off2 - off1) >> 2; | |
565 | u.addend = extra.addend; | |
566 | } | |
9543cb2f A |
567 | |
568 | ||
a645023d A |
569 | bool firstInCluster() const { |
570 | switch (clusterSize) { | |
571 | case k1of1: | |
572 | case k1of2: | |
573 | case k1of3: | |
574 | case k1of4: | |
575 | case k1of5: | |
576 | return true; | |
577 | default: | |
578 | break; | |
579 | } | |
580 | return false; | |
581 | } | |
582 | ||
583 | bool lastInCluster() const { | |
584 | switch (clusterSize) { | |
585 | case k1of1: | |
586 | case k2of2: | |
587 | case k3of3: | |
588 | case k4of4: | |
589 | case k5of5: | |
590 | return true; | |
591 | default: | |
592 | break; | |
593 | } | |
594 | return false; | |
595 | } | |
596 | ||
9543cb2f A |
597 | union LOH_arm64 { |
598 | uint64_t addend; | |
599 | struct { | |
600 | unsigned kind : 6, | |
601 | count : 2, // 00 => 1 addr, 11 => 4 addrs | |
602 | delta1 : 14, // 16-bit delta, low 2 bits assumed zero | |
603 | delta2 : 14, | |
604 | delta3 : 14, | |
605 | delta4 : 14; | |
606 | } info; | |
607 | }; | |
9543cb2f | 608 | |
a645023d A |
609 | }; |
610 | ||
611 | // | |
612 | // ld::Atom | |
613 | // | |
614 | // An atom is the fundamental unit of linking. A C function or global variable is an atom. | |
615 | // An atom has content and attributes. The content of a function atom is the instructions | |
616 | // that implement the function. The content of a global variable atom is its initial bits. | |
617 | // | |
618 | // Name: | |
619 | // The name of an atom is the label name generated by the compiler. A C compiler names foo() | |
620 | // as _foo. A C++ compiler names foo() as __Z3foov. | |
621 | // The name refers to the first byte of the content. An atom cannot have multiple entry points. | |
622 | // Such code is modeled as multiple atoms, each having a "follow on" reference to the next. | |
623 | // A "follow on" reference is a contraint to the linker to the atoms must be laid out contiguously. | |
624 | // | |
625 | // Scope: | |
626 | // An atom is in one of three scopes: translation-unit, linkage-unit, or global. These correspond | |
627 | // to the C visibility of static, hidden, default. | |
628 | // | |
629 | // DefinitionKind: | |
630 | // An atom is one of five defintion kinds: | |
631 | // regular Most atoms. | |
632 | // weak C++ compiler makes some functions weak if there might be multiple copies | |
633 | // that the linker needs to coalesce. | |
634 | // tentative A straggler from ancient C when the extern did not exist. "int foo;" is ambiguous. | |
635 | // It could be a prototype or it could be a definition. | |
636 | // external This is a "proxy" atom produced by a dylib reader. It has no content. It exists | |
637 | // so that the graph of Atoms can be complete. | |
638 | // external-weak Same as external, but the definition in the dylib is weak. | |
639 | // | |
640 | // SymbolTableInclusion: | |
641 | // An atom may or may not be in the symbol table in an object file. | |
642 | // in Most atoms for functions or global data | |
643 | // not-in Anonymous atoms such literal c-strings, or other compiler generated data | |
644 | // not-in-final Atom whose name should not be in the symbol table of final linkd image (e.g. 'l' labels .eh labels) | |
645 | // in-never-strip Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o) | |
646 | // | |
647 | // ContentType: | |
648 | // Some atoms require specially processing by the linker based on their content. For instance, zero-fill data | |
649 | // atom are group together at the end of the DATA segment to reduce disk size. | |
650 | // | |
651 | // ObjectAddress: | |
652 | // For reproducability, the linker lays out atoms in the order they occurred in the source (object) files. | |
653 | // The objectAddress() method returns the address of an atom in the object file so that the linker | |
654 | // can arrange the atoms. | |
655 | // | |
656 | // | |
657 | class Atom | |
658 | { | |
659 | public: | |
660 | enum Scope { scopeTranslationUnit, scopeLinkageUnit, scopeGlobal }; | |
661 | enum Definition { definitionRegular, definitionTentative, definitionAbsolute, definitionProxy }; | |
662 | enum Combine { combineNever, combineByName, combineByNameAndContent, combineByNameAndReferences }; | |
663 | enum ContentType { typeUnclassified, typeZeroFill, typeCString, typeCFI, typeLSDA, typeSectionStart, | |
664 | typeSectionEnd, typeBranchIsland, typeLazyPointer, typeStub, typeNonLazyPointer, | |
665 | typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers, | |
666 | typeLTOtemporary, typeResolver, | |
eaf282aa | 667 | typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers, typeTLVPointer }; |
a645023d A |
668 | |
669 | enum SymbolTableInclusion { symbolTableNotIn, symbolTableNotInFinalLinkedImages, symbolTableIn, | |
670 | symbolTableInAndNeverStrip, symbolTableInAsAbsolute, | |
671 | symbolTableInWithRandomAutoStripLabel }; | |
afe874b1 A |
672 | enum WeakImportState { weakImportUnset, weakImportTrue, weakImportFalse }; |
673 | ||
a645023d A |
674 | struct Alignment { |
675 | Alignment(int p2, int m=0) : powerOf2(p2), modulus(m) {} | |
676 | uint8_t trailingZeros() const { return (modulus==0) ? powerOf2 : __builtin_ctz(modulus); } | |
677 | uint16_t powerOf2; | |
678 | uint16_t modulus; | |
679 | }; | |
680 | struct LineInfo { | |
681 | const char* fileName; | |
682 | uint32_t atomOffset; | |
683 | uint32_t lineNumber; | |
684 | ||
685 | typedef LineInfo* iterator; | |
686 | }; | |
687 | struct UnwindInfo { | |
688 | uint32_t startOffset; | |
689 | uint32_t unwindInfo; | |
690 | ||
691 | typedef UnwindInfo* iterator; | |
692 | }; | |
693 | ||
694 | Atom(const Section& sect, Definition d, Combine c, Scope s, ContentType ct, | |
695 | SymbolTableInclusion i, bool dds, bool thumb, bool al, Alignment a) : | |
696 | _section(§), _address(0), _alignmentModulus(a.modulus), | |
697 | _alignmentPowerOf2(a.powerOf2), _definition(d), _combine(c), | |
698 | _dontDeadStrip(dds), _thumb(thumb), _alias(al), _autoHide(false), | |
699 | _contentType(ct), _symbolTableInclusion(i), | |
700 | _scope(s), _mode(modeSectionOffset), | |
701 | _overridesADylibsWeakDef(false), _coalescedAway(false), | |
eaf282aa A |
702 | _live(false), _dontDeadStripIfRefLive(false), |
703 | _machoSection(0), _weakImportState(weakImportUnset) | |
a645023d A |
704 | { |
705 | #ifndef NDEBUG | |
706 | switch ( _combine ) { | |
707 | case combineByNameAndContent: | |
708 | case combineByNameAndReferences: | |
f80fe69f | 709 | assert(_symbolTableInclusion != symbolTableIn); |
a645023d A |
710 | assert(_scope != scopeGlobal); |
711 | break; | |
712 | case combineByName: | |
713 | case combineNever: | |
714 | break; | |
715 | }; | |
716 | #endif | |
717 | } | |
718 | virtual ~Atom() {} | |
719 | ||
720 | const Section& section() const { return *_section; } | |
721 | Definition definition() const { return _definition; } | |
722 | Combine combine() const { return _combine; } | |
723 | Scope scope() const { return _scope; } | |
724 | ContentType contentType() const { return _contentType; } | |
725 | SymbolTableInclusion symbolTableInclusion() const{ return _symbolTableInclusion; } | |
726 | bool dontDeadStrip() const { return _dontDeadStrip; } | |
eaf282aa | 727 | bool dontDeadStripIfReferencesLive() const { return _dontDeadStripIfRefLive; } |
a645023d A |
728 | bool isThumb() const { return _thumb; } |
729 | bool isAlias() const { return _alias; } | |
730 | Alignment alignment() const { return Alignment(_alignmentPowerOf2, _alignmentModulus); } | |
731 | bool overridesDylibsWeakDef() const { return _overridesADylibsWeakDef; } | |
732 | bool coalescedAway() const { return _coalescedAway; } | |
afe874b1 A |
733 | bool weakImported() const { return _weakImportState == weakImportTrue; } |
734 | WeakImportState weakImportState() const { return _weakImportState; } | |
a645023d A |
735 | bool autoHide() const { return _autoHide; } |
736 | bool live() const { return _live; } | |
737 | uint8_t machoSection() const { assert(_machoSection != 0); return _machoSection; } | |
738 | ||
739 | void setScope(Scope s) { _scope = s; } | |
740 | void setSymbolTableInclusion(SymbolTableInclusion i) | |
741 | { _symbolTableInclusion = i; } | |
742 | void setCombine(Combine c) { _combine = c; } | |
743 | void setOverridesDylibsWeakDef() { _overridesADylibsWeakDef = true; } | |
744 | void setCoalescedAway() { _coalescedAway = true; } | |
afe874b1 | 745 | void setWeakImportState(bool w) { assert(_definition == definitionProxy); _weakImportState = ( w ? weakImportTrue : weakImportFalse); } |
a645023d | 746 | void setAutoHide() { _autoHide = true; } |
eaf282aa | 747 | void setDontDeadStripIfReferencesLive() { _dontDeadStripIfRefLive = true; } |
a645023d A |
748 | void setLive() { _live = true; } |
749 | void setLive(bool value) { _live = value; } | |
750 | void setMachoSection(unsigned x) { assert(x != 0); assert(x < 256); _machoSection = x; } | |
751 | void setSectionOffset(uint64_t o){ assert(_mode == modeSectionOffset); _address = o; _mode = modeSectionOffset; } | |
752 | void setSectionStartAddress(uint64_t a) { assert(_mode == modeSectionOffset); _address += a; _mode = modeFinalAddress; } | |
753 | uint64_t sectionOffset() const { assert(_mode == modeSectionOffset); return _address; } | |
754 | uint64_t finalAddress() const { assert(_mode == modeFinalAddress); return _address; } | |
ebf6f434 A |
755 | #ifndef NDEBUG |
756 | bool finalAddressMode() const { return (_mode == modeFinalAddress); } | |
757 | #endif | |
a645023d | 758 | virtual const File* file() const = 0; |
0a8dc3df A |
759 | // Return the original file this atom belongs to, for instance for an LTO atom, |
760 | // file() would return the LTO MachO file instead of the original bitcode file. | |
761 | virtual const ld::File* originalFile() const { return file(); } | |
b1f7435d | 762 | virtual const char* translationUnitSource() const { return NULL; } |
a645023d A |
763 | virtual const char* name() const = 0; |
764 | virtual uint64_t objectAddress() const = 0; | |
765 | virtual uint64_t size() const = 0; | |
766 | virtual void copyRawContent(uint8_t buffer[]) const = 0; | |
767 | virtual const uint8_t* rawContentPointer() const { return NULL; } | |
768 | virtual unsigned long contentHash(const class IndirectBindingTable&) const { return 0; } | |
769 | virtual bool canCoalesceWith(const Atom& rhs, const class IndirectBindingTable&) const { return false; } | |
770 | virtual Fixup::iterator fixupsBegin() const { return NULL; } | |
771 | virtual Fixup::iterator fixupsEnd() const { return NULL; } | |
ebf6f434 A |
772 | bool hasFixupsOfKind(Fixup::Kind kind) const { |
773 | for (ld::Fixup::iterator fit = fixupsBegin(), end=fixupsEnd(); fit != end; ++fit) { | |
774 | if ( fit->kind == kind ) return true; | |
775 | } | |
776 | return false; | |
777 | } | |
9543cb2f | 778 | virtual void setFile(const File* f) { } |
ebf6f434 | 779 | |
a645023d A |
780 | virtual UnwindInfo::iterator beginUnwind() const { return NULL; } |
781 | virtual UnwindInfo::iterator endUnwind() const { return NULL; } | |
782 | virtual LineInfo::iterator beginLineInfo() const { return NULL; } | |
783 | virtual LineInfo::iterator endLineInfo() const { return NULL; } | |
784 | ||
a645023d A |
785 | void setAttributesFromAtom(const Atom& a) { |
786 | _section = a._section; | |
787 | _alignmentModulus = a._alignmentModulus; | |
788 | _alignmentPowerOf2 = a._alignmentPowerOf2; | |
789 | _definition = a._definition; | |
790 | _combine = a._combine; | |
791 | _dontDeadStrip = a._dontDeadStrip; | |
82b4b32b | 792 | _dontDeadStripIfRefLive = a._dontDeadStripIfRefLive; |
a645023d | 793 | _thumb = a._thumb; |
a645023d A |
794 | _autoHide = a._autoHide; |
795 | _contentType = a._contentType; | |
796 | _symbolTableInclusion = a._symbolTableInclusion; | |
797 | _scope = a._scope; | |
798 | _mode = a._mode; | |
799 | _overridesADylibsWeakDef = a._overridesADylibsWeakDef; | |
800 | _coalescedAway = a._coalescedAway; | |
afe874b1 | 801 | _weakImportState = a._weakImportState; |
a645023d A |
802 | } |
803 | ||
82b4b32b A |
804 | const char* safeFilePath() const { |
805 | const File* f = this->file(); | |
806 | if ( f != NULL ) | |
807 | return f->path(); | |
808 | else | |
809 | return "<internal>"; | |
810 | } | |
811 | ||
599556ff A |
812 | protected: |
813 | enum AddressMode { modeSectionOffset, modeFinalAddress }; | |
814 | ||
a645023d A |
815 | const Section * _section; |
816 | uint64_t _address; | |
817 | uint16_t _alignmentModulus; | |
818 | uint8_t _alignmentPowerOf2; | |
819 | Definition _definition : 2; | |
820 | Combine _combine : 2; | |
821 | bool _dontDeadStrip : 1; | |
822 | bool _thumb : 1; | |
823 | bool _alias : 1; | |
824 | int _autoHide : 1; | |
825 | ContentType _contentType : 5; | |
826 | SymbolTableInclusion _symbolTableInclusion : 3; | |
827 | Scope _scope : 2; | |
828 | AddressMode _mode: 2; | |
829 | bool _overridesADylibsWeakDef : 1; | |
830 | bool _coalescedAway : 1; | |
a645023d | 831 | bool _live : 1; |
eaf282aa | 832 | bool _dontDeadStripIfRefLive : 1; |
a645023d | 833 | unsigned _machoSection : 8; |
afe874b1 | 834 | WeakImportState _weakImportState : 2; |
a645023d A |
835 | }; |
836 | ||
837 | ||
838 | class IndirectBindingTable | |
839 | { | |
840 | public: | |
841 | virtual const char* indirectName(uint32_t bindingIndex) const = 0; | |
842 | virtual const ld::Atom* indirectAtom(uint32_t bindingIndex) const = 0; | |
843 | }; | |
844 | ||
845 | ||
82b4b32b | 846 | |
f80fe69f A |
847 | // utility classes for using std::unordered_map with c-strings |
848 | struct CStringHash { | |
849 | size_t operator()(const char* __s) const { | |
850 | size_t __h = 0; | |
851 | for ( ; *__s; ++__s) | |
852 | __h = 5 * __h + *__s; | |
853 | return __h; | |
854 | }; | |
855 | }; | |
856 | struct CStringEquals | |
857 | { | |
858 | bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); } | |
859 | }; | |
860 | ||
861 | typedef std::unordered_set<const char*, ld::CStringHash, ld::CStringEquals> CStringSet; | |
862 | ||
eaf282aa | 863 | |
a645023d A |
864 | class Internal |
865 | { | |
866 | public: | |
867 | class FinalSection : public ld::Section { | |
868 | public: | |
869 | FinalSection(const Section& sect) : Section(sect), address(0), | |
870 | fileOffset(0), size(0), alignment(0), | |
871 | indirectSymTabStartIndex(0), indirectSymTabElementSize(0), | |
872 | relocStart(0), relocCount(0), | |
873 | hasLocalRelocs(false), hasExternalRelocs(false) {} | |
874 | std::vector<const Atom*> atoms; | |
875 | uint64_t address; | |
876 | uint64_t fileOffset; | |
877 | uint64_t size; | |
878 | uint32_t alignmentPaddingBytes; | |
879 | uint8_t alignment; | |
880 | uint32_t indirectSymTabStartIndex; | |
881 | uint32_t indirectSymTabElementSize; | |
882 | uint32_t relocStart; | |
883 | uint32_t relocCount; | |
884 | bool hasLocalRelocs; | |
885 | bool hasExternalRelocs; | |
886 | }; | |
887 | ||
eaf282aa A |
888 | typedef std::map<const ld::Atom*, FinalSection*> AtomToSection; |
889 | ||
9543cb2f A |
890 | virtual uint64_t assignFileOffsets() = 0; |
891 | virtual void setSectionSizesAndAlignments() = 0; | |
a645023d A |
892 | virtual ld::Internal::FinalSection* addAtom(const Atom&) = 0; |
893 | virtual ld::Internal::FinalSection* getFinalSection(const ld::Section& inputSection) = 0; | |
894 | virtual ~Internal() {} | |
895 | Internal() : bundleLoader(NULL), | |
896 | entryPoint(NULL), classicBindingHelper(NULL), | |
897 | lazyBindingHelper(NULL), compressedFastBinderProxy(NULL), | |
898 | objcObjectConstraint(ld::File::objcConstraintNone), | |
899 | objcDylibConstraint(ld::File::objcConstraintNone), | |
eaf282aa A |
900 | swiftVersion(0), cpuSubType(0), minOSVersion(0), |
901 | objectFileFoundWithNoVersion(false), | |
ebf6f434 | 902 | allObjectFilesScatterable(true), |
9543cb2f A |
903 | someObjectFileHasDwarf(false), usingHugeSections(false), |
904 | hasThreadLocalVariableDefinitions(false), | |
905 | hasWeakExternalSymbols(false), | |
eaf282aa | 906 | someObjectHasOptimizationHints(false), |
82b4b32b A |
907 | dropAllBitcode(false), embedMarkerOnly(false), |
908 | forceLoadCompilerRT(false) { } | |
eaf282aa | 909 | |
a645023d A |
910 | std::vector<FinalSection*> sections; |
911 | std::vector<ld::dylib::File*> dylibs; | |
0a8dc3df | 912 | std::vector<std::string> archivePaths; |
a645023d | 913 | std::vector<ld::relocatable::File::Stab> stabs; |
eaf282aa | 914 | AtomToSection atomToSection; |
0a8dc3df A |
915 | CStringSet unprocessedLinkerOptionLibraries; |
916 | CStringSet unprocessedLinkerOptionFrameworks; | |
f80fe69f A |
917 | CStringSet linkerOptionLibraries; |
918 | CStringSet linkerOptionFrameworks; | |
a645023d | 919 | std::vector<const ld::Atom*> indirectBindingTable; |
eaf282aa | 920 | std::vector<const ld::relocatable::File*> filesWithBitcode; |
82b4b32b | 921 | std::vector<const ld::relocatable::File*> filesFromCompilerRT; |
0a8dc3df | 922 | std::vector<const ld::Atom*> deadAtoms; |
ec29ba20 | 923 | std::unordered_set<const char*> allUndefProxies; |
bee7e226 | 924 | std::unordered_set<uint64_t> toolsVersions; |
a645023d A |
925 | const ld::dylib::File* bundleLoader; |
926 | const Atom* entryPoint; | |
927 | const Atom* classicBindingHelper; | |
928 | const Atom* lazyBindingHelper; | |
929 | const Atom* compressedFastBinderProxy; | |
930 | ld::File::ObjcConstraint objcObjectConstraint; | |
931 | ld::File::ObjcConstraint objcDylibConstraint; | |
599556ff | 932 | uint8_t swiftVersion; |
a645023d | 933 | uint32_t cpuSubType; |
eaf282aa | 934 | uint32_t minOSVersion; |
bee7e226 | 935 | uint32_t derivedPlatform; |
eaf282aa | 936 | bool objectFileFoundWithNoVersion; |
a645023d | 937 | bool allObjectFilesScatterable; |
a645023d A |
938 | bool someObjectFileHasDwarf; |
939 | bool usingHugeSections; | |
9543cb2f A |
940 | bool hasThreadLocalVariableDefinitions; |
941 | bool hasWeakExternalSymbols; | |
942 | bool someObjectHasOptimizationHints; | |
eaf282aa A |
943 | bool dropAllBitcode; |
944 | bool embedMarkerOnly; | |
82b4b32b | 945 | bool forceLoadCompilerRT; |
0a8dc3df | 946 | std::vector<std::string> ltoBitcodePath; |
a645023d A |
947 | }; |
948 | ||
949 | ||
950 | ||
a645023d A |
951 | |
952 | ||
953 | ||
954 | ||
a645023d A |
955 | } // namespace ld |
956 | ||
957 | #endif // __LD_HPP__ |