]> git.saurik.com Git - apple/ld64.git/blame_incremental - src/ld/ld.hpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / ld.hpp
... / ...
CommitLineData
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
42namespace ld {
43
44//
45// platform
46//
47
48enum Platform {
49 kPlatform_unknown=0,
50 kPlatform_macOS=1,
51 kPlatform_iOS=2,
52 kPlatform_tvOS=3,
53 kPlatform_watchOS=4,
54 kPlatform_bridgeOS=5,
55 kPlatform_iOSMac=6,
56 kPlatform_iOSSimulator=7,
57 kPlatform_tvOSSimulator=8,
58 kPlatform_watchOSSimulator=9
59};
60
61typedef std::set<Platform> PlatformSet;
62
63//
64// minumum OS versions
65//
66
67typedef std::pair<Platform, uint32_t> Version;
68
69struct VersionSet {
70private:
71 std::map<Platform, uint32_t> _versions;
72public:
73 VersionSet() {}
74 VersionSet(const std::map<Platform, uint32_t>& P) : _versions(P) {}
75 void add(ld::Version platformVersion) {
76 _versions.insert(platformVersion);
77 }
78 void erase(const Platform& platform) {
79 _versions.erase(platform);
80 }
81 size_t count() const { return _versions.size(); }
82 size_t empty() const { return _versions.empty(); }
83
84 void forEach(void (^callback)(ld::Platform platform, uint32_t version, bool &stop)) const {
85 bool stop = false;
86 for (const auto& version : _versions) {
87 callback(version.first, version.second, stop);
88 if (stop)
89 return;
90 }
91 }
92
93 bool contains(ld::Platform platform) const { return _versions.count(platform) != 0; }
94 bool contains(ld::PlatformSet platforms) const {
95 __block bool retval = true;
96 forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
97 if (platforms.find(platform) == platforms.end()) {
98 stop = true;
99 retval = false;
100 }
101 });
102 return retval;
103 }
104
105 uint32_t minOS(const ld::Platform& platform) const {
106 for (const auto& version : _versions) {
107 if (basePlatform(version.first) == platform) {
108 return version.second;
109 }
110 }
111 return 0;
112 }
113
114 bool minOS(const Version& version) const {
115 return minOS(version.first) >= version.second;
116 }
117
118 const ld::Platform basePlatform(const ld::Platform& platform) const {
119 switch(platform) {
120 case kPlatform_iOSMac:
121 case kPlatform_iOSSimulator:
122 return kPlatform_iOS;
123 case kPlatform_watchOSSimulator:
124 return kPlatform_watchOS;
125 case kPlatform_tvOSSimulator:
126 return kPlatform_tvOS;
127 default:
128 return platform;
129 }
130 }
131
132 bool minOS(const ld::VersionSet& requiredMinVersions) const {
133 __block bool retval = true;
134 forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
135 if (!requiredMinVersions.contains(basePlatform(platform)))
136 return;
137 if (version < requiredMinVersions.minOS(basePlatform(platform))) {
138 stop = true;
139 retval = false;
140 }
141 });
142 return retval;
143 }
144
145 std::string to_str() const {
146 std::string retval;
147 auto appendPlatform = [&](const std::string& platform) {
148 if (retval.empty()) {
149 retval = platform;
150 } else {
151 retval += "/";
152 retval += platform;
153 }
154 };
155
156 forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
157 switch (platform) {
158 case ld::kPlatform_macOS: appendPlatform("macOS"); break;
159 case ld::kPlatform_iOSMac: appendPlatform("iOSMac"); break;
160 case ld::kPlatform_iOS: appendPlatform("iOS"); break;
161 case ld::kPlatform_iOSSimulator: appendPlatform("iOS Simulator"); break;
162 case ld::kPlatform_watchOS: appendPlatform("watchOS"); break;
163 case ld::kPlatform_watchOSSimulator: appendPlatform("watchOS Simulator"); break;
164 case ld::kPlatform_tvOS: appendPlatform("tvOS"); break;
165 case ld::kPlatform_tvOSSimulator: appendPlatform("tvOS Simulator"); break;
166 case ld::kPlatform_bridgeOS: appendPlatform("bridgeOS"); break;
167 case ld::kPlatform_unknown: appendPlatform("Unkown"); break;
168 }
169 });
170
171 return retval;
172 }
173};
174
175static const Version mac10_4 ({kPlatform_macOS, 0x000A0400});
176static const Version mac10_5 ({kPlatform_macOS, 0x000A0500});
177static const Version mac10_6 ({kPlatform_macOS, 0x000A0600});
178static const Version mac10_7 ({kPlatform_macOS, 0x000A0700});
179static const Version mac10_8 ({kPlatform_macOS, 0x000A0800});
180static const Version mac10_9 ({kPlatform_macOS, 0x000A0900});
181static const Version mac10_12 ({kPlatform_macOS, 0x000A0C00});
182static const Version mac10_14 ({kPlatform_macOS, 0x000A0E00});
183static const Version mac10_Future ({kPlatform_macOS, 0x10000000});
184
185static const Version iOS_2_0 ({kPlatform_iOS, 0x00020000});
186static const Version iOS_3_1 ({kPlatform_iOS, 0x00030100});
187static const Version iOS_4_2 ({kPlatform_iOS, 0x00040200});
188static const Version iOS_4_3 ({kPlatform_iOS, 0x00040300});
189static const Version iOS_5_0 ({kPlatform_iOS, 0x00050000});
190static const Version iOS_6_0 ({kPlatform_iOS, 0x00060000});
191static const Version iOS_7_0 ({kPlatform_iOS, 0x00070000});
192static const Version iOS_8_0 ({kPlatform_iOS, 0x00080000});
193static const Version iOS_9_0 ({kPlatform_iOS, 0x00090000});
194static const Version iOS_10_0 ({kPlatform_iOS, 0x000A0000});
195static const Version iOS_11_0 ({kPlatform_iOS, 0x000B0000});
196static const Version iOS_12_0 ({kPlatform_iOS, 0x000C0000});
197static const Version iOS_Future ({kPlatform_iOS, 0x10000000});
198
199static const Version watchOS_1_0 ({kPlatform_watchOS, 0x00010000});
200static const Version watchOS_2_0 ({kPlatform_watchOS, 0x00020000});
201static const Version watchOS_5_0 ({kPlatform_watchOS, 0x00050000});
202static const Version watchOS_Future ({kPlatform_watchOS, 0x10000000});
203
204static const Version tvOS_9_0 ({kPlatform_tvOS, 0x00090000});
205static const Version tvOS_12_0 ({kPlatform_tvOS, 0x000C0000});
206static const Version tvOS_Future ({kPlatform_tvOS, 0x10000000});
207
208static const Version bridgeOS_1_0 ({kPlatform_bridgeOS, 0x00010000});
209static const Version bridgeOS_Future ({kPlatform_bridgeOS, 0x10000000});
210
211// Platform Sets
212
213static const PlatformSet simulatorPlatforms ( {kPlatform_iOSSimulator, kPlatform_tvOSSimulator, kPlatform_watchOSSimulator} );
214
215//FIXME do we need to add simulatots to these?
216//FIXME Are the dates correct?
217static const VersionSet version2007 ({mac10_4, iOS_2_0});
218static const VersionSet version2008 ({mac10_5, iOS_2_0});
219static const VersionSet version2008Fall ({mac10_5, iOS_3_1});
220static const VersionSet version2009 ({mac10_6, iOS_3_1});
221static const VersionSet version2010 ({mac10_7, iOS_4_2});
222static const VersionSet version2010Fall ({mac10_7, iOS_4_3});
223
224static const VersionSet version2012 ({mac10_8, iOS_6_0});
225static const VersionSet version2013 ({mac10_9, iOS_7_0});
226
227static const VersionSet supportsSplitSegV2 ({mac10_12, iOS_9_0, watchOS_2_0, tvOS_9_0});
228// FIXME: Use the comment out line instead.
229static const VersionSet supportsLCBuildVersion ({mac10_14, iOS_12_0, watchOS_5_0, tvOS_12_0, bridgeOS_1_0});
230static const VersionSet supportsPIE ({mac10_5, iOS_4_2});
231static const VersionSet supportsTLV ({mac10_7, iOS_9_0});
232
233// Forward declaration for bitcode support
234class Bitcode;
235
236//
237// ld::File
238//
239// Abstract base class for all object or library files the linker processes.
240//
241// forEachAtom() iterates over the Atoms in the order they occur in the file.
242//
243// justInTimeforEachAtom(name) iterates over lazily created Atoms. For instance if
244// File is a static library, justInTimeforEachAtom() will iterate over the base set
245// of Atoms from the archive member implementing 'name'.
246//
247class File
248{
249public:
250
251 class AtomHandler {
252 public:
253 virtual ~AtomHandler() {}
254 virtual void doAtom(const class Atom&) = 0;
255 virtual void doFile(const class File&) = 0;
256 };
257
258 //
259 // ld::File::Ordinal
260 //
261 // Codifies the rules of ordering input files for symbol precedence. These are:
262 // - Input files listed on the command line are ordered according to their index in the argument list.
263 // - Input files listed in a file list are ordered first at the index of the file list argument, then
264 // by index in the file list
265 // - Input files extracted from archives are ordered using the ordinal of the archive itself plus the
266 // index of the object file within the archive
267 // - Indirect dylibs are ordered after all input files derived from the command line, in the order that
268 // they are discovered.
269 // - The LTO object file is last.
270 //
271 class Ordinal
272 {
273 private:
274 // The actual numeric ordinal. Lower values have higher precedence and a zero value is invalid.
275 // The 64 bit ordinal is broken into 4 16 bit chunks. The high 16 bits are a "partition" that
276 // is used to distinguish major ordinal groups: command line, indirect dylib, LTO.
277 // The remaining chunks are used according to the partition (see below).
278 uint64_t _ordinal;
279
280 Ordinal (uint64_t ordinal) : _ordinal(ordinal) {}
281
282 enum { kArgListPartition=0, kIndirectDylibPartition=1, kLTOPartition = 2, kLinkerOptionPartition = 3, InvalidParition=0xffff };
283 Ordinal(uint16_t partition, uint16_t majorIndex, uint16_t minorIndex, uint16_t counter) {
284 _ordinal = ((uint64_t)partition<<48) | ((uint64_t)majorIndex<<32) | ((uint64_t)minorIndex<<16) | ((uint64_t)counter<<0);
285 }
286
287 const uint16_t partition() const { return (_ordinal>>48)&0xffff; }
288 const uint16_t majorIndex() const { return (_ordinal>>32)&0xffff; }
289 const uint16_t minorIndex() const { return (_ordinal>>16)&0xffff; }
290 const uint16_t counter() const { return (_ordinal>>00)&0xffff; }
291
292 const Ordinal nextMajorIndex() const { assert(majorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<32)); }
293 const Ordinal nextMinorIndex() const { assert(minorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<16)); }
294 const Ordinal nextCounter() const { assert(counter() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<0)); }
295
296 public:
297 Ordinal() : _ordinal(0) {};
298
299 static const Ordinal NullOrdinal() { return Ordinal((uint64_t)0); }
300
301 const bool validOrdinal() const { return _ordinal != 0; }
302
303 bool operator ==(const Ordinal& rhs) const { return _ordinal == rhs._ordinal; }
304 bool operator !=(const Ordinal& rhs) const { return _ordinal != rhs._ordinal; }
305 bool operator < (const Ordinal& rhs) const { return _ordinal < rhs._ordinal; }
306 bool operator > (const Ordinal& rhs) const { return _ordinal > rhs._ordinal; }
307
308 // For ordinals derived from the command line args the partition is ArgListPartition
309 // The majorIndex is the arg index that pulls in the file, file list, or archive.
310 // 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.
311 // The counter is used for .a files and the value is the index of the object in the archive.
312 // Thus, an object pulled in from a .a that was listed in a file list could use all three fields.
313 static const Ordinal makeArgOrdinal(uint16_t argIndex) { return Ordinal(kArgListPartition, argIndex, 0, 0); };
314 const Ordinal nextFileListOrdinal() const { return nextMinorIndex(); }
315 const Ordinal archiveOrdinalWithMemberIndex(uint16_t memberIndex) const { return Ordinal(partition(), majorIndex(), minorIndex(), memberIndex); }
316
317 // For indirect libraries the partition is IndirectDylibPartition and the counter is used or order the libraries.
318 static const ld::File::Ordinal indirectDylibBase() { return Ordinal(kIndirectDylibPartition, 0, 0, 0); }
319 const Ordinal nextIndirectDylibOrdinal() const { return nextCounter(); }
320
321 // For the LTO mach-o the partition is LTOPartition. As there is only one LTO file no other fields are needed.
322 static const ld::File::Ordinal LTOOrdinal() { return Ordinal(kLTOPartition, 0, 0, 0); }
323
324 // For linker options embedded in object files
325 static const ld::File::Ordinal linkeOptionBase() { return Ordinal(kIndirectDylibPartition, 1, 0, 0); }
326 const Ordinal nextLinkerOptionOrdinal() { return nextCounter(); };
327
328 };
329
330 typedef enum { Reloc, Dylib, Archive, Other } Type;
331
332 File(const char* pth, time_t modTime, Ordinal ord, Type type)
333 : _path(pth), _modTime(modTime), _ordinal(ord), _type(type) { }
334 virtual ~File() {}
335 const char* path() const { return _path; }
336 time_t modificationTime() const{ return _modTime; }
337 Ordinal ordinal() const { return _ordinal; }
338 virtual bool forEachAtom(AtomHandler&) const = 0;
339 virtual bool justInTimeforEachAtom(const char* name, AtomHandler&) const = 0;
340 virtual uint8_t swiftVersion() const { return 0; }
341 virtual uint32_t cpuSubType() const { return 0; }
342 virtual uint32_t subFileCount() const { return 1; }
343 virtual const VersionSet& platforms() const { return _platforms; }
344 bool fileExists() const { return _modTime != 0; }
345 Type type() const { return _type; }
346 virtual Bitcode* getBitcode() const { return NULL; }
347private:
348 const char* _path;
349 time_t _modTime;
350 const Ordinal _ordinal;
351 const Type _type;
352 // Note this is just a placeholder as platforms() needs something to return
353 static const VersionSet _platforms;
354};
355
356namespace relocatable {
357 //
358 // ld::relocatable::File
359 //
360 // Abstract base class for object files the linker processes.
361 //
362 // debugInfo() returns if the object file contains debugger information (stabs or dwarf).
363 //
364 // stabs() lazily creates a vector of Stab objects for each atom
365 //
366 // canScatterAtoms() true for all compiler generated code. Hand written assembly can opt-in
367 // via .subsections_via_symbols directive. When true it means the linker can break up section
368 // content at symbol boundaries and do optimizations like coalescing, dead code stripping, or
369 // apply order files.
370 //
371 // optimize() used by libLTO to lazily generate code from llvm bit-code files
372 //
373 class File : public ld::File
374 {
375 public:
376 enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 };
377 enum SourceKind { kSourceUnknown=0, kSourceObj, kSourceLTO, kSourceArchive, kSourceCompilerArchive };
378 struct Stab {
379 const class Atom* atom;
380 uint8_t type;
381 uint8_t other;
382 uint16_t desc;
383 uint32_t value;
384 const char* string;
385 };
386 typedef const std::vector< std::vector<const char*> > LinkerOptionsList;
387 typedef std::vector<std::pair<uint32_t,uint32_t>> ToolVersionList;
388 struct AstTimeAndPath { uint64_t time; std::string path; };
389
390 File(const char* pth, time_t modTime, Ordinal ord)
391 : ld::File(pth, modTime, ord, Reloc) { }
392 virtual ~File() {}
393 virtual DebugInfoKind debugInfo() const = 0;
394 virtual const char* debugInfoPath() const { return path(); }
395 virtual time_t debugInfoModificationTime() const { return modificationTime(); }
396 virtual const std::vector<Stab>* stabs() const = 0;
397 virtual bool canScatterAtoms() const = 0;
398 virtual bool hasLongBranchStubs() { return false; }
399 virtual bool hasllvmProfiling() const { return false; }
400 virtual bool hasObjC() const { return false; }
401 virtual bool objcHasCategoryClassPropertiesField() const { return false; }
402 virtual LinkerOptionsList* linkerOptions() const = 0;
403 virtual const ToolVersionList& toolVersions() const = 0;
404 virtual SourceKind sourceKind() const { return kSourceUnknown; }
405 virtual const uint8_t* fileContent() const { return nullptr; }
406 virtual const std::vector<AstTimeAndPath>* astFiles() const { return nullptr; }
407 };
408} // namespace relocatable
409
410
411namespace dylib {
412
413 //
414 // ld::dylib::File
415 //
416 // Abstract base class for dynamic shared libraries read by the linker processes.
417 //
418 class File : public ld::File
419 {
420 public:
421 class DylibHandler
422 {
423 public:
424 virtual ~DylibHandler() {}
425 virtual File* findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative) = 0;
426 };
427
428 File(const char* pth, time_t modTime, Ordinal ord)
429 : ld::File(pth, modTime, ord, Dylib), _dylibInstallPath(NULL), _frameworkName(NULL),
430 _dylibTimeStamp(0), _dylibCurrentVersion(0), _dylibCompatibilityVersion(0),
431 _explicitlyLinked(false), _implicitlyLinked(false), _speculativelyLoaded(false),
432 _lazyLoadedDylib(false), _forcedWeakLinked(false), _reExported(false),
433 _upward(false), _dead(false) { }
434 const char* installPath() const { return _dylibInstallPath; }
435 const char* frameworkName() const { return _frameworkName; }
436 uint32_t timestamp() const { return _dylibTimeStamp; }
437 uint32_t currentVersion() const { return _dylibCurrentVersion; }
438 uint32_t compatibilityVersion() const{ return _dylibCompatibilityVersion; }
439 void setExplicitlyLinked() { _explicitlyLinked = true; }
440 bool explicitlyLinked() const { return _explicitlyLinked; }
441 void setImplicitlyLinked() { _implicitlyLinked = true; }
442 bool implicitlyLinked() const { return _implicitlyLinked; }
443 void setSpeculativelyLoaded() { _speculativelyLoaded = true; }
444 bool speculativelyLoaded() const { return _speculativelyLoaded; }
445
446 // attributes of how dylib will be used when linked
447 void setWillBeLazyLoadedDylb() { _lazyLoadedDylib = true; }
448 bool willBeLazyLoadedDylib() const { return _lazyLoadedDylib; }
449 void setForcedWeakLinked() { _forcedWeakLinked = true; }
450 bool forcedWeakLinked() const { return _forcedWeakLinked; }
451
452 void setWillBeReExported() { _reExported = true; }
453 bool willBeReExported() const { return _reExported; }
454 void setWillBeUpwardDylib() { _upward = true; }
455 bool willBeUpwardDylib() const { return _upward; }
456 void setWillBeRemoved(bool value) { _dead = value; }
457 bool willRemoved() const { return _dead; }
458
459 virtual void processIndirectLibraries(DylibHandler* handler, bool addImplicitDylibs) = 0;
460 virtual bool providedExportAtom() const = 0;
461 virtual const char* parentUmbrella() const = 0;
462 virtual const std::vector<const char*>* allowableClients() const = 0;
463 virtual const std::vector<const char*>& rpaths() const = 0;
464 virtual bool hasWeakExternals() const = 0;
465 virtual bool deadStrippable() const = 0;
466 virtual bool hasWeakDefinition(const char* name) const = 0;
467 virtual bool hasPublicInstallName() const = 0;
468 virtual bool allSymbolsAreWeakImported() const = 0;
469 virtual bool installPathVersionSpecific() const { return false; }
470 virtual bool appExtensionSafe() const = 0;
471
472 public:
473 const char* _dylibInstallPath;
474 const char* _frameworkName;
475 uint32_t _dylibTimeStamp;
476 uint32_t _dylibCurrentVersion;
477 uint32_t _dylibCompatibilityVersion;
478 bool _explicitlyLinked;
479 bool _implicitlyLinked;
480 bool _speculativelyLoaded;
481 bool _lazyLoadedDylib;
482 bool _forcedWeakLinked;
483 bool _reExported;
484 bool _upward;
485 bool _dead;
486 };
487} // namespace dylib
488
489
490namespace archive {
491 //
492 // ld::archive::File
493 //
494 // Abstract base class for static libraries read by the linker processes.
495 //
496 class File : public ld::File
497 {
498 public:
499 File(const char* pth, time_t modTime, Ordinal ord)
500 : ld::File(pth, modTime, ord, Archive) { }
501 virtual ~File() {}
502 virtual bool justInTimeDataOnlyforEachAtom(const char* name, AtomHandler&) const = 0;
503 };
504} // namespace archive
505
506
507//
508// ld::Section
509//
510class Section
511{
512public:
513 enum Type { typeUnclassified, typeCode, typePageZero, typeImportProxies, typeLinkEdit, typeMachHeader, typeStack,
514 typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO, typeTempAlias,
515 typeCString, typeNonStdCString, typeCStringPointer, typeUTF16Strings, typeCFString, typeObjC1Classes,
516 typeCFI, typeLSDA, typeDtraceDOF, typeUnwindInfo, typeObjCClassRefs, typeObjC2CategoryList,
517 typeZeroFill, typeTentativeDefs, typeLazyPointer, typeStub, typeNonLazyPointer, typeDyldInfo,
518 typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
519 typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols, typeThreadStarts,
520 typeTLVDefs, typeTLVZeroFill, typeTLVInitialValues, typeTLVInitializerPointers, typeTLVPointers,
521 typeFirstSection, typeLastSection, typeDebug, typeSectCreate };
522
523
524 Section(const char* sgName, const char* sctName,
525 Type t, bool hidden=false)
526 : _segmentName(sgName), _sectionName(sctName),
527 _type(t), _hidden(hidden) {}
528 Section(const Section& sect)
529 : _segmentName(sect.segmentName()), _sectionName(sect.sectionName()),
530 _type(sect.type()), _hidden(sect.isSectionHidden()) {}
531
532 bool operator==(const Section& rhs) const { return ( (_hidden==rhs._hidden) &&
533 (strcmp(_segmentName, rhs._segmentName)==0) &&
534 (strcmp(_sectionName, rhs._sectionName)==0) ); }
535 bool operator!=(const Section& rhs) const { return ! (*this == rhs); }
536 const char* segmentName() const { return _segmentName; }
537 const char* sectionName() const { return _sectionName; }
538 Type type() const { return _type; }
539 bool isSectionHidden() const { return _hidden; }
540
541private:
542 const char* _segmentName;
543 const char* _sectionName;
544 Type _type;
545 bool _hidden;
546};
547
548
549
550//
551// ld::Fixup
552//
553// A Fixup describes how part of an Atom's content must be fixed up. For instance,
554// an instruction may contain a displacement to another Atom that must be
555// fixed up by the linker.
556//
557// A Fixup my reference another Atom. There are two kinds of references: direct and by-name.
558// With a direct reference, the target is bound by the File that created it.
559// For instance a reference to a static would produce a direct reference.
560// A by-name reference requires the linker to find the target Atom with the
561// required name in order to be bound.
562//
563// For a link to succeed all Fixup must be bound.
564//
565// A Reference also has a fix-up-offset. This is the offset into the content of the
566// Atom holding the reference where the fix-up (relocation) will be applied.
567//
568//
569struct Fixup
570{
571 enum TargetBinding { bindingNone, bindingByNameUnbound, bindingDirectlyBound, bindingByContentBound, bindingsIndirectlyBound };
572 enum Cluster { k1of1, k1of2, k2of2, k1of3, k2of3, k3of3, k1of4, k2of4, k3of4, k4of4, k1of5, k2of5, k3of5, k4of5, k5of5 };
573 enum Kind { kindNone, kindNoneFollowOn,
574 // grouping
575 kindNoneGroupSubordinate,
576 kindNoneGroupSubordinateFDE, kindNoneGroupSubordinateLSDA, kindNoneGroupSubordinatePersonality,
577 // value calculations
578 kindSetTargetAddress,
579 kindSubtractTargetAddress,
580 kindAddAddend,
581 kindSubtractAddend,
582 kindSetTargetImageOffset,
583 kindSetTargetSectionOffset,
584 kindSetTargetTLVTemplateOffset,
585 // pointer store kinds (of current calculated value)
586 kindStore8,
587 kindStoreLittleEndian16,
588 kindStoreLittleEndianLow24of32,
589 kindStoreLittleEndian32,
590 kindStoreLittleEndian64,
591 kindStoreBigEndian16,
592 kindStoreBigEndianLow24of32,
593 kindStoreBigEndian32,
594 kindStoreBigEndian64,
595 // Intel specific store kinds
596 kindStoreX86BranchPCRel8, kindStoreX86BranchPCRel32,
597 kindStoreX86PCRel8, kindStoreX86PCRel16,
598 kindStoreX86PCRel32, kindStoreX86PCRel32_1, kindStoreX86PCRel32_2, kindStoreX86PCRel32_4,
599 kindStoreX86PCRel32GOTLoad, kindStoreX86PCRel32GOTLoadNowLEA, kindStoreX86PCRel32GOT,
600 kindStoreX86PCRel32TLVLoad, kindStoreX86PCRel32TLVLoadNowLEA,
601 kindStoreX86Abs32TLVLoad, kindStoreX86Abs32TLVLoadNowLEA,
602 // ARM specific store kinds
603 kindStoreARMBranch24, kindStoreThumbBranch22,
604 kindStoreARMLoad12,
605 kindStoreARMLow16, kindStoreARMHigh16,
606 kindStoreThumbLow16, kindStoreThumbHigh16,
607#if SUPPORT_ARCH_arm64
608 // ARM64 specific store kinds
609 kindStoreARM64Branch26,
610 kindStoreARM64Page21, kindStoreARM64PageOff12,
611 kindStoreARM64GOTLoadPage21, kindStoreARM64GOTLoadPageOff12,
612 kindStoreARM64GOTLeaPage21, kindStoreARM64GOTLeaPageOff12,
613 kindStoreARM64TLVPLoadPage21, kindStoreARM64TLVPLoadPageOff12,
614 kindStoreARM64TLVPLoadNowLeaPage21, kindStoreARM64TLVPLoadNowLeaPageOff12,
615 kindStoreARM64PointerToGOT, kindStoreARM64PCRelToGOT,
616#endif
617 // dtrace probes
618 kindDtraceExtra,
619 kindStoreX86DtraceCallSiteNop, kindStoreX86DtraceIsEnableSiteClear,
620 kindStoreARMDtraceCallSiteNop, kindStoreARMDtraceIsEnableSiteClear,
621 kindStoreARM64DtraceCallSiteNop, kindStoreARM64DtraceIsEnableSiteClear,
622 kindStoreThumbDtraceCallSiteNop, kindStoreThumbDtraceIsEnableSiteClear,
623 // lazy binding
624 kindLazyTarget, kindSetLazyOffset,
625 // islands
626 kindIslandTarget,
627 // data-in-code markers
628 kindDataInCodeStartData, kindDataInCodeStartJT8, kindDataInCodeStartJT16,
629 kindDataInCodeStartJT32, kindDataInCodeStartJTA32, kindDataInCodeEnd,
630 // linker optimization hints
631 kindLinkerOptimizationHint,
632 // pointer store combinations
633 kindStoreTargetAddressLittleEndian32, // kindSetTargetAddress + kindStoreLittleEndian32
634 kindStoreTargetAddressLittleEndian64, // kindSetTargetAddress + kindStoreLittleEndian64
635 kindStoreTargetAddressBigEndian32, // kindSetTargetAddress + kindStoreBigEndian32
636 kindStoreTargetAddressBigEndian64, // kindSetTargetAddress + kindStoreBigEndian364
637 kindSetTargetTLVTemplateOffsetLittleEndian32, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian32
638 kindSetTargetTLVTemplateOffsetLittleEndian64, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian64
639 // Intel value calculation and store combinations
640 kindStoreTargetAddressX86PCRel32, // kindSetTargetAddress + kindStoreX86PCRel32
641 kindStoreTargetAddressX86BranchPCRel32, // kindSetTargetAddress + kindStoreX86BranchPCRel32
642 kindStoreTargetAddressX86PCRel32GOTLoad,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoad
643 kindStoreTargetAddressX86PCRel32GOTLoadNowLEA,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoadNowLEA
644 kindStoreTargetAddressX86PCRel32TLVLoad, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoad
645 kindStoreTargetAddressX86PCRel32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoadNowLEA
646 kindStoreTargetAddressX86Abs32TLVLoad, // kindSetTargetAddress + kindStoreX86Abs32TLVLoad
647 kindStoreTargetAddressX86Abs32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86Abs32TLVLoadNowLEA
648 // ARM value calculation and store combinations
649 kindStoreTargetAddressARMBranch24, // kindSetTargetAddress + kindStoreARMBranch24
650 kindStoreTargetAddressThumbBranch22, // kindSetTargetAddress + kindStoreThumbBranch22
651 kindStoreTargetAddressARMLoad12, // kindSetTargetAddress + kindStoreARMLoad12
652#if SUPPORT_ARCH_arm64
653 // ARM64 value calculation and store combinations
654 kindStoreTargetAddressARM64Branch26, // kindSetTargetAddress + kindStoreARM64Branch26
655 kindStoreTargetAddressARM64Page21, // kindSetTargetAddress + kindStoreARM64Page21
656 kindStoreTargetAddressARM64PageOff12, // kindSetTargetAddress + kindStoreARM64PageOff12
657 kindStoreTargetAddressARM64GOTLoadPage21, // kindSetTargetAddress + kindStoreARM64GOTLoadPage21
658 kindStoreTargetAddressARM64GOTLoadPageOff12,// kindSetTargetAddress + kindStoreARM64GOTLoadPageOff12
659 kindStoreTargetAddressARM64GOTLeaPage21, // kindSetTargetAddress + kindStoreARM64GOTLeaPage21
660 kindStoreTargetAddressARM64GOTLeaPageOff12, // kindSetTargetAddress + kindStoreARM64GOTLeaPageOff12
661 kindStoreTargetAddressARM64TLVPLoadPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadPage21
662 kindStoreTargetAddressARM64TLVPLoadPageOff12,// kindSetTargetAddress + kindStoreARM64TLVPLoadPageOff12
663 kindStoreTargetAddressARM64TLVPLoadNowLeaPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPage21
664 kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPageOff12
665#endif
666#if SUPPORT_ARCH_arm64e
667 kindStoreLittleEndianAuth64,
668 kindStoreTargetAddressLittleEndianAuth64, // kindSetTargetAddress + kindStoreLittleEndianAuth64
669 kindSetAuthData,
670#endif
671 };
672
673#if SUPPORT_ARCH_arm64e
674 struct AuthData {
675 // clang encodes the combination of the key bits as these values.
676 typedef enum {
677 ptrauth_key_asia = 0,
678 ptrauth_key_asib = 1,
679 ptrauth_key_asda = 2,
680 ptrauth_key_asdb = 3,
681 } ptrauth_key;
682
683 uint16_t discriminator;
684 bool hasAddressDiversity;
685 ptrauth_key key;
686 };
687#endif
688
689 union {
690 const Atom* target;
691 const char* name;
692 uint64_t addend;
693 uint32_t bindingIndex;
694#if SUPPORT_ARCH_arm64e
695 AuthData authData;
696#endif
697 } u;
698 uint32_t offsetInAtom;
699 Kind kind : 8;
700 Cluster clusterSize : 4;
701 bool weakImport : 1;
702 TargetBinding binding : 3;
703 bool contentAddendOnly : 1;
704 bool contentDetlaToAddendOnly : 1;
705 bool contentIgnoresAddend : 1;
706
707 typedef Fixup* iterator;
708
709 Fixup() :
710 offsetInAtom(0), kind(kindNone), clusterSize(k1of1), weakImport(false),
711 binding(bindingNone),
712 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) { u.target = NULL; }
713
714 Fixup(Kind k, Atom* targetAtom) :
715 offsetInAtom(0), kind(k), clusterSize(k1of1), weakImport(false),
716 binding(Fixup::bindingDirectlyBound),
717 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
718 { assert(targetAtom != NULL); u.target = targetAtom; }
719
720 Fixup(uint32_t off, Cluster c, Kind k) :
721 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
722 binding(Fixup::bindingNone),
723 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
724 { u.addend = 0; }
725
726 Fixup(uint32_t off, Cluster c, Kind k, bool weakIm, const char* name) :
727 offsetInAtom(off), kind(k), clusterSize(c), weakImport(weakIm),
728 binding(Fixup::bindingByNameUnbound),
729 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
730 { assert(name != NULL); u.name = name; }
731
732 Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const char* name) :
733 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b),
734 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
735 { assert(name != NULL); u.name = name; }
736
737 Fixup(uint32_t off, Cluster c, Kind k, const Atom* targetAtom) :
738 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
739 binding(Fixup::bindingDirectlyBound),
740 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
741 { assert(targetAtom != NULL); u.target = targetAtom; }
742
743 Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const Atom* targetAtom) :
744 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b),
745 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
746 { assert(targetAtom != NULL); u.target = targetAtom; }
747
748 Fixup(uint32_t off, Cluster c, Kind k, uint64_t addend) :
749 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
750 binding(Fixup::bindingNone),
751 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
752 { u.addend = addend; }
753
754#if SUPPORT_ARCH_arm64e
755 Fixup(uint32_t off, Cluster c, Kind k, AuthData authData) :
756 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
757 binding(Fixup::bindingNone),
758 contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
759 { u.authData = authData; }
760#endif
761
762 Fixup(Kind k, uint32_t lohKind, uint32_t off1, uint32_t off2) :
763 offsetInAtom(off1), kind(k), clusterSize(k1of1),
764 weakImport(false), binding(Fixup::bindingNone), contentAddendOnly(false),
765 contentDetlaToAddendOnly(false), contentIgnoresAddend(false) {
766 assert(k == kindLinkerOptimizationHint);
767 LOH_arm64 extra;
768 extra.addend = 0;
769 extra.info.kind = lohKind;
770 extra.info.count = 1;
771 extra.info.delta1 = 0;
772 extra.info.delta2 = (off2 - off1) >> 2;
773 u.addend = extra.addend;
774 }
775
776
777 bool firstInCluster() const {
778 switch (clusterSize) {
779 case k1of1:
780 case k1of2:
781 case k1of3:
782 case k1of4:
783 case k1of5:
784 return true;
785 default:
786 break;
787 }
788 return false;
789 }
790
791 bool lastInCluster() const {
792 switch (clusterSize) {
793 case k1of1:
794 case k2of2:
795 case k3of3:
796 case k4of4:
797 case k5of5:
798 return true;
799 default:
800 break;
801 }
802 return false;
803 }
804
805 bool isStore() const {
806 switch ( kind ) {
807 case ld::Fixup::kindNone:
808 case ld::Fixup::kindNoneFollowOn:
809 case ld::Fixup::kindNoneGroupSubordinate:
810 case ld::Fixup::kindNoneGroupSubordinateFDE:
811 case ld::Fixup::kindNoneGroupSubordinateLSDA:
812 case ld::Fixup::kindNoneGroupSubordinatePersonality:
813 case ld::Fixup::kindSetTargetAddress:
814 case ld::Fixup::kindSubtractTargetAddress:
815 case ld::Fixup::kindAddAddend:
816 case ld::Fixup::kindSubtractAddend:
817 case ld::Fixup::kindSetTargetImageOffset:
818 case ld::Fixup::kindSetTargetSectionOffset:
819#if SUPPORT_ARCH_arm64e
820 case ld::Fixup::kindSetAuthData:
821#endif
822 return false;
823 default:
824 break;
825 }
826 return true;
827 }
828
829
830 bool setsTarget(bool isObjectFile) const {
831 switch ( kind ) {
832 case ld::Fixup::kindSetTargetAddress:
833 case ld::Fixup::kindLazyTarget:
834 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
835 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
836#if SUPPORT_ARCH_arm64e
837 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
838#endif
839 case ld::Fixup::kindStoreTargetAddressBigEndian32:
840 case ld::Fixup::kindStoreTargetAddressBigEndian64:
841 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
842 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
843 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
844 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
845 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
846 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
847 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
848 case ld::Fixup::kindStoreTargetAddressARMBranch24:
849 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
850 case ld::Fixup::kindStoreTargetAddressARMLoad12:
851#if SUPPORT_ARCH_arm64
852 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
853 case ld::Fixup::kindStoreTargetAddressARM64Page21:
854 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
855 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
856 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
857 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
858 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
859 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
860 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
861 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
862 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
863#endif
864 return true;
865 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
866 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
867 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
868 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
869 case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
870 case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
871 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
872 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
873 return isObjectFile;
874 default:
875 break;
876 }
877 return false;
878 }
879
880 bool isPcRelStore(bool isKextBundle) const {
881 switch ( kind ) {
882 case ld::Fixup::kindStoreX86BranchPCRel8:
883 case ld::Fixup::kindStoreX86BranchPCRel32:
884 case ld::Fixup::kindStoreX86PCRel8:
885 case ld::Fixup::kindStoreX86PCRel16:
886 case ld::Fixup::kindStoreX86PCRel32:
887 case ld::Fixup::kindStoreX86PCRel32_1:
888 case ld::Fixup::kindStoreX86PCRel32_2:
889 case ld::Fixup::kindStoreX86PCRel32_4:
890 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
891 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
892 case ld::Fixup::kindStoreX86PCRel32GOT:
893 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
894 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
895 case ld::Fixup::kindStoreARMBranch24:
896 case ld::Fixup::kindStoreThumbBranch22:
897 case ld::Fixup::kindStoreARMLoad12:
898 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
899 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
900 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
901 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
902 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
903 case ld::Fixup::kindStoreTargetAddressARMBranch24:
904 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
905 case ld::Fixup::kindStoreTargetAddressARMLoad12:
906#if SUPPORT_ARCH_arm64
907 case ld::Fixup::kindStoreARM64Page21:
908 case ld::Fixup::kindStoreARM64PageOff12:
909 case ld::Fixup::kindStoreARM64GOTLoadPage21:
910 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
911 case ld::Fixup::kindStoreARM64GOTLeaPage21:
912 case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
913 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
914 case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
915 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
916 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
917 case ld::Fixup::kindStoreARM64PCRelToGOT:
918 case ld::Fixup::kindStoreTargetAddressARM64Page21:
919 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
920 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
921 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
922 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
923 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
924 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
925 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
926 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
927 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
928#endif
929 return true;
930 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
931#if SUPPORT_ARCH_arm64
932 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
933#endif
934 return !isKextBundle;
935#if SUPPORT_ARCH_arm64
936 case ld::Fixup::kindStoreARM64Branch26:
937#endif
938 return !isKextBundle;
939 default:
940 break;
941 }
942 return false;
943 }
944
945 union LOH_arm64 {
946 uint64_t addend;
947 struct {
948 unsigned kind : 6,
949 count : 2, // 00 => 1 addr, 11 => 4 addrs
950 delta1 : 14, // 16-bit delta, low 2 bits assumed zero
951 delta2 : 14,
952 delta3 : 14,
953 delta4 : 14;
954 } info;
955 };
956
957};
958
959//
960// ld::Atom
961//
962// An atom is the fundamental unit of linking. A C function or global variable is an atom.
963// An atom has content and attributes. The content of a function atom is the instructions
964// that implement the function. The content of a global variable atom is its initial bits.
965//
966// Name:
967// The name of an atom is the label name generated by the compiler. A C compiler names foo()
968// as _foo. A C++ compiler names foo() as __Z3foov.
969// The name refers to the first byte of the content. An atom cannot have multiple entry points.
970// Such code is modeled as multiple atoms, each having a "follow on" reference to the next.
971// A "follow on" reference is a contraint to the linker to the atoms must be laid out contiguously.
972//
973// Scope:
974// An atom is in one of three scopes: translation-unit, linkage-unit, or global. These correspond
975// to the C visibility of static, hidden, default.
976//
977// DefinitionKind:
978// An atom is one of five defintion kinds:
979// regular Most atoms.
980// weak C++ compiler makes some functions weak if there might be multiple copies
981// that the linker needs to coalesce.
982// tentative A straggler from ancient C when the extern did not exist. "int foo;" is ambiguous.
983// It could be a prototype or it could be a definition.
984// external This is a "proxy" atom produced by a dylib reader. It has no content. It exists
985// so that the graph of Atoms can be complete.
986// external-weak Same as external, but the definition in the dylib is weak.
987//
988// SymbolTableInclusion:
989// An atom may or may not be in the symbol table in an object file.
990// in Most atoms for functions or global data
991// not-in Anonymous atoms such literal c-strings, or other compiler generated data
992// not-in-final Atom whose name should not be in the symbol table of final linkd image (e.g. 'l' labels .eh labels)
993// in-never-strip Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o)
994//
995// ContentType:
996// Some atoms require specially processing by the linker based on their content. For instance, zero-fill data
997// atom are group together at the end of the DATA segment to reduce disk size.
998//
999// ObjectAddress:
1000// For reproducability, the linker lays out atoms in the order they occurred in the source (object) files.
1001// The objectAddress() method returns the address of an atom in the object file so that the linker
1002// can arrange the atoms.
1003//
1004//
1005class Atom
1006{
1007public:
1008 enum Scope { scopeTranslationUnit, scopeLinkageUnit, scopeGlobal };
1009 enum Definition { definitionRegular, definitionTentative, definitionAbsolute, definitionProxy };
1010 enum Combine { combineNever, combineByName, combineByNameAndContent, combineByNameAndReferences };
1011 enum ContentType { typeUnclassified, typeZeroFill, typeCString, typeCFI, typeLSDA, typeSectionStart,
1012 typeSectionEnd, typeBranchIsland, typeLazyPointer, typeStub, typeNonLazyPointer,
1013 typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
1014 typeLTOtemporary, typeResolver,
1015 typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers, typeTLVPointer };
1016
1017 enum SymbolTableInclusion { symbolTableNotIn, symbolTableNotInFinalLinkedImages, symbolTableIn,
1018 symbolTableInAndNeverStrip, symbolTableInAsAbsolute,
1019 symbolTableInWithRandomAutoStripLabel };
1020 enum WeakImportState { weakImportUnset, weakImportTrue, weakImportFalse };
1021
1022 struct Alignment {
1023 Alignment(int p2, int m=0) : powerOf2(p2), modulus(m) {}
1024 uint8_t trailingZeros() const { return (modulus==0) ? powerOf2 : __builtin_ctz(modulus); }
1025 uint16_t powerOf2;
1026 uint16_t modulus;
1027 };
1028 struct LineInfo {
1029 const char* fileName;
1030 uint32_t atomOffset;
1031 uint32_t lineNumber;
1032
1033 typedef LineInfo* iterator;
1034 };
1035 struct UnwindInfo {
1036 uint32_t startOffset;
1037 uint32_t unwindInfo;
1038
1039 typedef UnwindInfo* iterator;
1040 };
1041
1042 Atom(const Section& sect, Definition d, Combine c, Scope s, ContentType ct,
1043 SymbolTableInclusion i, bool dds, bool thumb, bool al, Alignment a) :
1044 _section(&sect), _address(0), _alignmentModulus(a.modulus),
1045 _alignmentPowerOf2(a.powerOf2), _definition(d), _combine(c),
1046 _dontDeadStrip(dds), _thumb(thumb), _alias(al), _autoHide(false),
1047 _contentType(ct), _symbolTableInclusion(i),
1048 _scope(s), _mode(modeSectionOffset),
1049 _overridesADylibsWeakDef(false), _coalescedAway(false),
1050 _live(false), _dontDeadStripIfRefLive(false),
1051 _machoSection(0), _weakImportState(weakImportUnset)
1052 {
1053 #ifndef NDEBUG
1054 switch ( _combine ) {
1055 case combineByNameAndContent:
1056 case combineByNameAndReferences:
1057 assert(_symbolTableInclusion != symbolTableIn);
1058 assert(_scope != scopeGlobal);
1059 break;
1060 case combineByName:
1061 case combineNever:
1062 break;
1063 };
1064 #endif
1065 }
1066 virtual ~Atom() {}
1067
1068 const Section& section() const { return *_section; }
1069 Definition definition() const { return _definition; }
1070 Combine combine() const { return _combine; }
1071 Scope scope() const { return _scope; }
1072 ContentType contentType() const { return _contentType; }
1073 SymbolTableInclusion symbolTableInclusion() const{ return _symbolTableInclusion; }
1074 bool dontDeadStrip() const { return _dontDeadStrip; }
1075 bool dontDeadStripIfReferencesLive() const { return _dontDeadStripIfRefLive; }
1076 bool isThumb() const { return _thumb; }
1077 bool isAlias() const { return _alias; }
1078 Alignment alignment() const { return Alignment(_alignmentPowerOf2, _alignmentModulus); }
1079 bool overridesDylibsWeakDef() const { return _overridesADylibsWeakDef; }
1080 bool coalescedAway() const { return _coalescedAway; }
1081 bool weakImported() const { return _weakImportState == weakImportTrue; }
1082 WeakImportState weakImportState() const { return _weakImportState; }
1083 bool autoHide() const { return _autoHide; }
1084 bool live() const { return _live; }
1085 uint8_t machoSection() const { assert(_machoSection != 0); return _machoSection; }
1086
1087 void setScope(Scope s) { _scope = s; }
1088 void setSymbolTableInclusion(SymbolTableInclusion i)
1089 { _symbolTableInclusion = i; }
1090 void setCombine(Combine c) { _combine = c; }
1091 void setOverridesDylibsWeakDef() { _overridesADylibsWeakDef = true; }
1092 void setCoalescedAway() { _coalescedAway = true; }
1093 void setWeakImportState(bool w) { assert(_definition == definitionProxy); _weakImportState = ( w ? weakImportTrue : weakImportFalse); }
1094 void setAutoHide() { _autoHide = true; }
1095 void setDontDeadStripIfReferencesLive() { _dontDeadStripIfRefLive = true; }
1096 void setLive() { _live = true; }
1097 void setLive(bool value) { _live = value; }
1098 void setMachoSection(unsigned x) { assert(x != 0); assert(x < 256); _machoSection = x; }
1099 void setSectionOffset(uint64_t o){ assert(_mode == modeSectionOffset); _address = o; _mode = modeSectionOffset; }
1100 void setSectionStartAddress(uint64_t a) { assert(_mode == modeSectionOffset); _address += a; _mode = modeFinalAddress; }
1101 uint64_t sectionOffset() const { assert(_mode == modeSectionOffset); return _address; }
1102 uint64_t finalAddress() const { assert(_mode == modeFinalAddress); return _address; }
1103#ifndef NDEBUG
1104 bool finalAddressMode() const { return (_mode == modeFinalAddress); }
1105#endif
1106 virtual const File* file() const = 0;
1107 // Return the original file this atom belongs to, for instance for an LTO atom,
1108 // file() would return the LTO MachO file instead of the original bitcode file.
1109 virtual const ld::File* originalFile() const { return file(); }
1110 virtual const char* translationUnitSource() const { return NULL; }
1111 virtual const char* name() const = 0;
1112 virtual uint64_t objectAddress() const = 0;
1113 virtual uint64_t size() const = 0;
1114 virtual void copyRawContent(uint8_t buffer[]) const = 0;
1115 virtual const uint8_t* rawContentPointer() const { return NULL; }
1116 virtual unsigned long contentHash(const class IndirectBindingTable&) const { return 0; }
1117 virtual bool canCoalesceWith(const Atom& rhs, const class IndirectBindingTable&) const { return false; }
1118 virtual Fixup::iterator fixupsBegin() const { return NULL; }
1119 virtual Fixup::iterator fixupsEnd() const { return NULL; }
1120 bool hasFixupsOfKind(Fixup::Kind kind) const {
1121 for (ld::Fixup::iterator fit = fixupsBegin(), end=fixupsEnd(); fit != end; ++fit) {
1122 if ( fit->kind == kind ) return true;
1123 }
1124 return false;
1125 }
1126 virtual void setFile(const File* f) { }
1127
1128 virtual UnwindInfo::iterator beginUnwind() const { return NULL; }
1129 virtual UnwindInfo::iterator endUnwind() const { return NULL; }
1130 virtual LineInfo::iterator beginLineInfo() const { return NULL; }
1131 virtual LineInfo::iterator endLineInfo() const { return NULL; }
1132
1133 void setAttributesFromAtom(const Atom& a) {
1134 _section = a._section;
1135 _alignmentModulus = a._alignmentModulus;
1136 _alignmentPowerOf2 = a._alignmentPowerOf2;
1137 _definition = a._definition;
1138 _combine = a._combine;
1139 _dontDeadStrip = a._dontDeadStrip;
1140 _dontDeadStripIfRefLive = a._dontDeadStripIfRefLive;
1141 _thumb = a._thumb;
1142 _autoHide = a._autoHide;
1143 _contentType = a._contentType;
1144 _symbolTableInclusion = a._symbolTableInclusion;
1145 _scope = a._scope;
1146 _mode = a._mode;
1147 _overridesADylibsWeakDef = a._overridesADylibsWeakDef;
1148 _coalescedAway = a._coalescedAway;
1149 _weakImportState = a._weakImportState;
1150 }
1151
1152 const char* safeFilePath() const {
1153 const File* f = this->file();
1154 if ( f != NULL )
1155 return f->path();
1156 else
1157 return "<internal>";
1158 }
1159
1160protected:
1161 enum AddressMode { modeSectionOffset, modeFinalAddress };
1162
1163 const Section * _section;
1164 uint64_t _address;
1165 uint16_t _alignmentModulus;
1166 uint8_t _alignmentPowerOf2;
1167 Definition _definition : 2;
1168 Combine _combine : 2;
1169 bool _dontDeadStrip : 1;
1170 bool _thumb : 1;
1171 bool _alias : 1;
1172 int _autoHide : 1;
1173 ContentType _contentType : 5;
1174 SymbolTableInclusion _symbolTableInclusion : 3;
1175 Scope _scope : 2;
1176 AddressMode _mode: 2;
1177 bool _overridesADylibsWeakDef : 1;
1178 bool _coalescedAway : 1;
1179 bool _live : 1;
1180 bool _dontDeadStripIfRefLive : 1;
1181 unsigned _machoSection : 8;
1182 WeakImportState _weakImportState : 2;
1183};
1184
1185
1186class IndirectBindingTable
1187{
1188public:
1189 virtual const char* indirectName(uint32_t bindingIndex) const = 0;
1190 virtual const ld::Atom* indirectAtom(uint32_t bindingIndex) const = 0;
1191};
1192
1193
1194
1195// utility classes for using std::unordered_map with c-strings
1196struct CStringHash {
1197 size_t operator()(const char* __s) const {
1198 size_t __h = 0;
1199 for ( ; *__s; ++__s)
1200 __h = 5 * __h + *__s;
1201 return __h;
1202 };
1203};
1204struct CStringEquals
1205{
1206 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
1207};
1208
1209typedef std::unordered_set<const char*, ld::CStringHash, ld::CStringEquals> CStringSet;
1210
1211
1212class Internal
1213{
1214public:
1215 class FinalSection : public ld::Section {
1216 public:
1217 FinalSection(const Section& sect) : Section(sect), address(0),
1218 fileOffset(0), size(0), alignment(0),
1219 indirectSymTabStartIndex(0), indirectSymTabElementSize(0),
1220 relocStart(0), relocCount(0),
1221 hasLocalRelocs(false), hasExternalRelocs(false) {}
1222 std::vector<const Atom*> atoms;
1223 uint64_t address;
1224 uint64_t fileOffset;
1225 uint64_t size;
1226 uint32_t alignmentPaddingBytes;
1227 uint8_t alignment;
1228 uint32_t indirectSymTabStartIndex;
1229 uint32_t indirectSymTabElementSize;
1230 uint32_t relocStart;
1231 uint32_t relocCount;
1232 bool hasLocalRelocs;
1233 bool hasExternalRelocs;
1234 };
1235
1236 typedef std::map<const ld::Atom*, FinalSection*> AtomToSection;
1237
1238 virtual uint64_t assignFileOffsets() = 0;
1239 virtual void setSectionSizesAndAlignments() = 0;
1240 virtual ld::Internal::FinalSection* addAtom(const Atom&) = 0;
1241 virtual ld::Internal::FinalSection* getFinalSection(const ld::Section& inputSection) = 0;
1242 virtual ~Internal() {}
1243 Internal() : bundleLoader(NULL),
1244 entryPoint(NULL), classicBindingHelper(NULL),
1245 lazyBindingHelper(NULL), compressedFastBinderProxy(NULL),
1246 hasObjC(false),
1247 swiftVersion(0), cpuSubType(0), minOSVersion(0),
1248 objectFileFoundWithNoVersion(false),
1249 allObjectFilesScatterable(true),
1250 someObjectFileHasDwarf(false), usingHugeSections(false),
1251 someObjectFileHasSwift(false), firstSwiftDylibFile(nullptr),
1252 hasThreadLocalVariableDefinitions(false),
1253 hasWeakExternalSymbols(false),
1254 someObjectHasOptimizationHints(false),
1255 dropAllBitcode(false), embedMarkerOnly(false),
1256 forceLoadCompilerRT(false) { }
1257
1258 std::vector<FinalSection*> sections;
1259 std::vector<ld::dylib::File*> dylibs;
1260 std::vector<std::string> archivePaths;
1261 std::vector<ld::relocatable::File::Stab> stabs;
1262 AtomToSection atomToSection;
1263 CStringSet unprocessedLinkerOptionLibraries;
1264 CStringSet unprocessedLinkerOptionFrameworks;
1265 CStringSet linkerOptionLibraries;
1266 CStringSet linkerOptionFrameworks;
1267 CStringSet missingLinkerOptionLibraries;
1268 CStringSet missingLinkerOptionFrameworks;
1269 std::vector<const ld::Atom*> indirectBindingTable;
1270 std::vector<const ld::relocatable::File*> filesWithBitcode;
1271 std::vector<const ld::relocatable::File*> filesFromCompilerRT;
1272 std::vector<const ld::Atom*> deadAtoms;
1273 std::unordered_set<const char*> allUndefProxies;
1274 std::unordered_set<uint64_t> toolsVersions;
1275 const ld::dylib::File* bundleLoader;
1276 const Atom* entryPoint;
1277 const Atom* classicBindingHelper;
1278 const Atom* lazyBindingHelper;
1279 const Atom* compressedFastBinderProxy;
1280 bool hasObjC;
1281 uint8_t swiftVersion;
1282 uint32_t cpuSubType;
1283 uint32_t minOSVersion;
1284 VersionSet derivedPlatforms;
1285 bool objectFileFoundWithNoVersion;
1286 bool allObjectFilesScatterable;
1287 bool someObjectFileHasDwarf;
1288 bool usingHugeSections;
1289 bool someObjectFileHasSwift;
1290 const ld::dylib::File* firstSwiftDylibFile;
1291 bool hasThreadLocalVariableDefinitions;
1292 bool hasWeakExternalSymbols;
1293 bool someObjectHasOptimizationHints;
1294 bool dropAllBitcode;
1295 bool embedMarkerOnly;
1296 bool forceLoadCompilerRT;
1297 std::vector<std::string> ltoBitcodePath;
1298};
1299
1300
1301
1302
1303
1304
1305
1306} // namespace ld
1307
1308#endif // __LD_HPP__