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