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