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