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