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