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