]> git.saurik.com Git - apple/ld64.git/blob - src/ld/ld.hpp
e5319bbdaec48e38544fdf35bcdcf8a6b0e4617c
[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 IPhoneVersionMin { iPhoneVersionUnset=0, iPhone2_0=0x00020000, iPhone3_1=0x00030100,
87 iPhone4_2=0x00040200, iPhone4_3=0x00040300 };
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), _weakLinked(false), _reExported(false),
157 _upward(false), _hasNonWeakImportedSymbols(false),
158 _hasWeakImportedSymbols(false), _dead(false) { }
159 const char* installPath() const { return _dylibInstallPath; }
160 uint32_t timestamp() const { return _dylibTimeStamp; }
161 uint32_t currentVersion() const { return _dylibCurrentVersion; }
162 uint32_t compatibilityVersion() const{ return _dylibCompatibilityVersion; }
163 void setExplicitlyLinked() { _explicitlyLinked = true; }
164 bool explicitlyLinked() const { return _explicitlyLinked; }
165 void setImplicitlyLinked() { _implicitlyLinked = true; }
166 bool implicitlyLinked() const { return _implicitlyLinked; }
167 // attributes of how dylib will be used when linked
168 void setWillBeLazyLoadedDylb() { _lazyLoadedDylib = true; }
169 bool willBeLazyLoadedDylib() const { return _lazyLoadedDylib; }
170 void setWillBeWeakLinked() { _weakLinked = true; }
171 bool willBeWeakLinked() const { return _weakLinked ||
172 (_hasWeakImportedSymbols && !_hasNonWeakImportedSymbols); }
173 void setWillBeReExported() { _reExported = true; }
174 bool willBeReExported() const { return _reExported; }
175 void setWillBeUpwardDylib() { _upward = true; }
176 bool willBeUpwardDylib() const { return _upward; }
177 void setUsingNonWeakImportedSymbols(){ _hasNonWeakImportedSymbols = true; }
178 void setUsingWeakImportedSymbols() { _hasWeakImportedSymbols = true; }
179 void setWillBeRemoved(bool value) { _dead = value; }
180 bool willRemoved() const { return _dead; }
181
182 virtual void processIndirectLibraries(DylibHandler* handler, bool addImplicitDylibs) = 0;
183 virtual bool providedExportAtom() const = 0;
184 virtual const char* parentUmbrella() const = 0;
185 virtual const std::vector<const char*>* allowableClients() const = 0;
186 virtual bool hasWeakExternals() const = 0;
187 virtual bool deadStrippable() const = 0;
188 virtual bool hasWeakDefinition(const char* name) const = 0;
189 virtual bool hasPublicInstallName() const = 0;
190 protected:
191 const char* _dylibInstallPath;
192 uint32_t _dylibTimeStamp;
193 uint32_t _dylibCurrentVersion;
194 uint32_t _dylibCompatibilityVersion;
195 bool _explicitlyLinked;
196 bool _implicitlyLinked;
197 bool _lazyLoadedDylib;
198 bool _weakLinked;
199 bool _reExported;
200 bool _upward;
201 bool _hasNonWeakImportedSymbols;
202 bool _hasWeakImportedSymbols;
203 bool _dead;
204 };
205 } // namespace dylib
206
207
208
209 //
210 // ld::Section
211 //
212 class Section
213 {
214 public:
215 enum Type { typeUnclassified, typeCode, typePageZero, typeImportProxies, typeLinkEdit, typeMachHeader, typeStack,
216 typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO,
217 typeCString, typeNonStdCString, typeCStringPointer, typeUTF16Strings, typeCFString, typeObjC1Classes,
218 typeCFI, typeLSDA, typeDtraceDOF, typeUnwindInfo, typeObjCClassRefs, typeObjC2CategoryList,
219 typeZeroFill, typeTentativeDefs, typeLazyPointer, typeStub, typeNonLazyPointer, typeDyldInfo,
220 typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
221 typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols,
222 typeTLVDefs, typeTLVZeroFill, typeTLVInitialValues, typeTLVInitializerPointers, typeTLVPointers,
223 typeFirstSection, typeLastSection };
224
225
226 Section(const char* sgName, const char* sctName,
227 Type t, bool hidden=false)
228 : _segmentName(sgName), _sectionName(sctName),
229 _type(t), _hidden(hidden) {}
230 Section(const Section& sect)
231 : _segmentName(sect.segmentName()), _sectionName(sect.sectionName()),
232 _type(sect.type()), _hidden(sect.isSectionHidden()) {}
233
234 bool operator==(const Section& rhs) const { return ( (_hidden==rhs._hidden) &&
235 (strcmp(_segmentName, rhs._segmentName)==0) &&
236 (strcmp(_sectionName, rhs._sectionName)==0) ); }
237 bool operator!=(const Section& rhs) const { return ! (*this == rhs); }
238 const char* segmentName() const { return _segmentName; }
239 const char* sectionName() const { return _sectionName; }
240 Type type() const { return _type; }
241 bool isSectionHidden() const { return _hidden; }
242
243 private:
244 const char* _segmentName;
245 const char* _sectionName;
246 Type _type;
247 bool _hidden;
248 };
249
250
251
252 //
253 // ld::Fixup
254 //
255 // A Fixup describes how part of an Atom's content must be fixed up. For instance,
256 // an instruction may contain a displacement to another Atom that must be
257 // fixed up by the linker.
258 //
259 // A Fixup my reference another Atom. There are two kinds of references: direct and by-name.
260 // With a direct reference, the target is bound by the File that created it.
261 // For instance a reference to a static would produce a direct reference.
262 // A by-name reference requires the linker to find the target Atom with the
263 // required name in order to be bound.
264 //
265 // For a link to succeed all Fixup must be bound.
266 //
267 // A Reference also has a fix-up-offset. This is the offset into the content of the
268 // Atom holding the reference where the fix-up (relocation) will be applied.
269 //
270 //
271 struct Fixup
272 {
273 enum TargetBinding { bindingNone, bindingByNameUnbound, bindingDirectlyBound, bindingByContentBound, bindingsIndirectlyBound };
274 enum Cluster { k1of1, k1of2, k2of2, k1of3, k2of3, k3of3, k1of4, k2of4, k3of4, k4of4, k1of5, k2of5, k3of5, k4of5, k5of5 };
275 enum Kind { kindNone, kindNoneFollowOn,
276 // grouping
277 kindNoneGroupSubordinate,
278 kindNoneGroupSubordinateFDE, kindNoneGroupSubordinateLSDA, kindNoneGroupSubordinatePersonality,
279 // value calculations
280 kindSetTargetAddress,
281 kindSubtractTargetAddress,
282 kindAddAddend,
283 kindSubtractAddend,
284 kindSetTargetImageOffset,
285 kindSetTargetSectionOffset,
286 kindSetTargetTLVTemplateOffset,
287 // pointer store kinds (of current calculated value)
288 kindStore8,
289 kindStoreLittleEndian16,
290 kindStoreLittleEndianLow24of32,
291 kindStoreLittleEndian32,
292 kindStoreLittleEndian64,
293 kindStoreBigEndian16,
294 kindStoreBigEndianLow24of32,
295 kindStoreBigEndian32,
296 kindStoreBigEndian64,
297 // Intel specific store kinds
298 kindStoreX86BranchPCRel8, kindStoreX86BranchPCRel32,
299 kindStoreX86PCRel8, kindStoreX86PCRel16,
300 kindStoreX86PCRel32, kindStoreX86PCRel32_1, kindStoreX86PCRel32_2, kindStoreX86PCRel32_4,
301 kindStoreX86PCRel32GOTLoad, kindStoreX86PCRel32GOTLoadNowLEA, kindStoreX86PCRel32GOT,
302 kindStoreX86PCRel32TLVLoad, kindStoreX86PCRel32TLVLoadNowLEA,
303 kindStoreX86Abs32TLVLoad, kindStoreX86Abs32TLVLoadNowLEA,
304 // ARM specific store kinds
305 kindStoreARMBranch24, kindStoreThumbBranch22,
306 kindStoreARMLoad12,
307 kindStoreARMLow16, kindStoreARMHigh16,
308 kindStoreThumbLow16, kindStoreThumbHigh16,
309 // PowerPC specific store kinds
310 kindStorePPCBranch24, kindStorePPCBranch14,
311 kindStorePPCPicLow14, kindStorePPCPicLow16, kindStorePPCPicHigh16AddLow,
312 kindStorePPCAbsLow14, kindStorePPCAbsLow16, kindStorePPCAbsHigh16AddLow, kindStorePPCAbsHigh16,
313 // dtrace probes
314 kindDtraceExtra,
315 kindStoreX86DtraceCallSiteNop, kindStoreX86DtraceIsEnableSiteClear,
316 kindStoreARMDtraceCallSiteNop, kindStoreARMDtraceIsEnableSiteClear,
317 kindStoreThumbDtraceCallSiteNop, kindStoreThumbDtraceIsEnableSiteClear,
318 kindStorePPCDtraceCallSiteNop, kindStorePPCDtraceIsEnableSiteClear,
319 // lazy binding
320 kindLazyTarget, kindSetLazyOffset,
321 // pointer store combinations
322 kindStoreTargetAddressLittleEndian32, // kindSetTargetAddress + kindStoreLittleEndian32
323 kindStoreTargetAddressLittleEndian64, // kindSetTargetAddress + kindStoreLittleEndian64
324 kindStoreTargetAddressBigEndian32, // kindSetTargetAddress + kindStoreBigEndian32
325 kindStoreTargetAddressBigEndian64, // kindSetTargetAddress + kindStoreBigEndian364
326 kindSetTargetTLVTemplateOffsetLittleEndian32, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian32
327 kindSetTargetTLVTemplateOffsetLittleEndian64, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian64
328 // Intel value calculation and store combinations
329 kindStoreTargetAddressX86PCRel32, // kindSetTargetAddress + kindStoreX86PCRel32
330 kindStoreTargetAddressX86BranchPCRel32, // kindSetTargetAddress + kindStoreX86BranchPCRel32
331 kindStoreTargetAddressX86PCRel32GOTLoad,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoad
332 kindStoreTargetAddressX86PCRel32GOTLoadNowLEA,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoadNowLEA
333 kindStoreTargetAddressX86PCRel32TLVLoad, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoad
334 kindStoreTargetAddressX86PCRel32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoadNowLEA
335 kindStoreTargetAddressX86Abs32TLVLoad, // kindSetTargetAddress + kindStoreX86Abs32TLVLoad
336 kindStoreTargetAddressX86Abs32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86Abs32TLVLoadNowLEA
337 // ARM value calculation and store combinations
338 kindStoreTargetAddressARMBranch24, // kindSetTargetAddress + kindStoreARMBranch24
339 kindStoreTargetAddressThumbBranch22, // kindSetTargetAddress + kindStoreThumbBranch22
340 kindStoreTargetAddressARMLoad12, // kindSetTargetAddress + kindStoreARMLoad12
341 // PowerPC value calculation and store combinations
342 kindStoreTargetAddressPPCBranch24, // kindSetTargetAddress + kindStorePPCBranch24
343 };
344
345 union {
346 const Atom* target;
347 const char* name;
348 uint64_t addend;
349 uint32_t bindingIndex;
350 } u;
351 uint32_t offsetInAtom;
352 Kind kind : 8;
353 Cluster clusterSize : 4;
354 bool weakImport : 1;
355 TargetBinding binding : 3;
356 bool contentAddendOnly : 1;
357 bool contentDetlaToAddendOnly : 1;
358
359 typedef Fixup* iterator;
360
361 Fixup() :
362 offsetInAtom(0), kind(kindNone), clusterSize(k1of1), weakImport(false),
363 binding(bindingNone),
364 contentAddendOnly(false), contentDetlaToAddendOnly(false) { u.target = NULL; }
365
366 Fixup(Kind k, Atom* targetAtom) :
367 offsetInAtom(0), kind(k), clusterSize(k1of1), weakImport(false),
368 binding(Fixup::bindingDirectlyBound),
369 contentAddendOnly(false), contentDetlaToAddendOnly(false)
370 { assert(targetAtom != NULL); u.target = targetAtom; }
371
372 Fixup(uint32_t off, Cluster c, Kind k) :
373 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
374 binding(Fixup::bindingNone),
375 contentAddendOnly(false), contentDetlaToAddendOnly(false)
376 { u.addend = 0; }
377
378 Fixup(uint32_t off, Cluster c, Kind k, bool weakIm, const char* name) :
379 offsetInAtom(off), kind(k), clusterSize(c), weakImport(weakIm),
380 binding(Fixup::bindingByNameUnbound),
381 contentAddendOnly(false), contentDetlaToAddendOnly(false)
382 { assert(name != NULL); u.name = name; }
383
384 Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const char* name) :
385 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b),
386 contentAddendOnly(false), contentDetlaToAddendOnly(false)
387 { assert(name != NULL); u.name = name; }
388
389 Fixup(uint32_t off, Cluster c, Kind k, const Atom* targetAtom) :
390 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
391 binding(Fixup::bindingDirectlyBound),
392 contentAddendOnly(false), contentDetlaToAddendOnly(false)
393 { assert(targetAtom != NULL); u.target = targetAtom; }
394
395 Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const Atom* targetAtom) :
396 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b),
397 contentAddendOnly(false), contentDetlaToAddendOnly(false)
398 { assert(targetAtom != NULL); u.target = targetAtom; }
399
400 Fixup(uint32_t off, Cluster c, Kind k, uint64_t addend) :
401 offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
402 binding(Fixup::bindingNone),
403 contentAddendOnly(false), contentDetlaToAddendOnly(false)
404 { u.addend = addend; }
405
406 bool firstInCluster() const {
407 switch (clusterSize) {
408 case k1of1:
409 case k1of2:
410 case k1of3:
411 case k1of4:
412 case k1of5:
413 return true;
414 default:
415 break;
416 }
417 return false;
418 }
419
420 bool lastInCluster() const {
421 switch (clusterSize) {
422 case k1of1:
423 case k2of2:
424 case k3of3:
425 case k4of4:
426 case k5of5:
427 return true;
428 default:
429 break;
430 }
431 return false;
432 }
433
434 };
435
436 //
437 // ld::Atom
438 //
439 // An atom is the fundamental unit of linking. A C function or global variable is an atom.
440 // An atom has content and attributes. The content of a function atom is the instructions
441 // that implement the function. The content of a global variable atom is its initial bits.
442 //
443 // Name:
444 // The name of an atom is the label name generated by the compiler. A C compiler names foo()
445 // as _foo. A C++ compiler names foo() as __Z3foov.
446 // The name refers to the first byte of the content. An atom cannot have multiple entry points.
447 // Such code is modeled as multiple atoms, each having a "follow on" reference to the next.
448 // A "follow on" reference is a contraint to the linker to the atoms must be laid out contiguously.
449 //
450 // Scope:
451 // An atom is in one of three scopes: translation-unit, linkage-unit, or global. These correspond
452 // to the C visibility of static, hidden, default.
453 //
454 // DefinitionKind:
455 // An atom is one of five defintion kinds:
456 // regular Most atoms.
457 // weak C++ compiler makes some functions weak if there might be multiple copies
458 // that the linker needs to coalesce.
459 // tentative A straggler from ancient C when the extern did not exist. "int foo;" is ambiguous.
460 // It could be a prototype or it could be a definition.
461 // external This is a "proxy" atom produced by a dylib reader. It has no content. It exists
462 // so that the graph of Atoms can be complete.
463 // external-weak Same as external, but the definition in the dylib is weak.
464 //
465 // SymbolTableInclusion:
466 // An atom may or may not be in the symbol table in an object file.
467 // in Most atoms for functions or global data
468 // not-in Anonymous atoms such literal c-strings, or other compiler generated data
469 // not-in-final Atom whose name should not be in the symbol table of final linkd image (e.g. 'l' labels .eh labels)
470 // in-never-strip Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o)
471 //
472 // ContentType:
473 // Some atoms require specially processing by the linker based on their content. For instance, zero-fill data
474 // atom are group together at the end of the DATA segment to reduce disk size.
475 //
476 // ObjectAddress:
477 // For reproducability, the linker lays out atoms in the order they occurred in the source (object) files.
478 // The objectAddress() method returns the address of an atom in the object file so that the linker
479 // can arrange the atoms.
480 //
481 //
482 class Atom
483 {
484 public:
485 enum Scope { scopeTranslationUnit, scopeLinkageUnit, scopeGlobal };
486 enum Definition { definitionRegular, definitionTentative, definitionAbsolute, definitionProxy };
487 enum Combine { combineNever, combineByName, combineByNameAndContent, combineByNameAndReferences };
488 enum ContentType { typeUnclassified, typeZeroFill, typeCString, typeCFI, typeLSDA, typeSectionStart,
489 typeSectionEnd, typeBranchIsland, typeLazyPointer, typeStub, typeNonLazyPointer,
490 typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
491 typeLTOtemporary, typeResolver,
492 typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers };
493
494 enum SymbolTableInclusion { symbolTableNotIn, symbolTableNotInFinalLinkedImages, symbolTableIn,
495 symbolTableInAndNeverStrip, symbolTableInAsAbsolute,
496 symbolTableInWithRandomAutoStripLabel };
497 struct Alignment {
498 Alignment(int p2, int m=0) : powerOf2(p2), modulus(m) {}
499 uint8_t trailingZeros() const { return (modulus==0) ? powerOf2 : __builtin_ctz(modulus); }
500 uint16_t powerOf2;
501 uint16_t modulus;
502 };
503 struct LineInfo {
504 const char* fileName;
505 uint32_t atomOffset;
506 uint32_t lineNumber;
507
508 typedef LineInfo* iterator;
509 };
510 struct UnwindInfo {
511 uint32_t startOffset;
512 uint32_t unwindInfo;
513
514 typedef UnwindInfo* iterator;
515 };
516
517 Atom(const Section& sect, Definition d, Combine c, Scope s, ContentType ct,
518 SymbolTableInclusion i, bool dds, bool thumb, bool al, Alignment a) :
519 _section(&sect), _address(0), _alignmentModulus(a.modulus),
520 _alignmentPowerOf2(a.powerOf2), _definition(d), _combine(c),
521 _dontDeadStrip(dds), _thumb(thumb), _alias(al), _autoHide(false),
522 _contentType(ct), _symbolTableInclusion(i),
523 _scope(s), _mode(modeSectionOffset),
524 _overridesADylibsWeakDef(false), _coalescedAway(false),
525 _weakImport(false), _live(false), _machoSection(0)
526 {
527 #ifndef NDEBUG
528 switch ( _combine ) {
529 case combineByNameAndContent:
530 case combineByNameAndReferences:
531 assert(_symbolTableInclusion == symbolTableNotIn);
532 assert(_scope != scopeGlobal);
533 break;
534 case combineByName:
535 case combineNever:
536 break;
537 };
538 #endif
539 }
540 virtual ~Atom() {}
541
542 const Section& section() const { return *_section; }
543 Definition definition() const { return _definition; }
544 Combine combine() const { return _combine; }
545 Scope scope() const { return _scope; }
546 ContentType contentType() const { return _contentType; }
547 SymbolTableInclusion symbolTableInclusion() const{ return _symbolTableInclusion; }
548 bool dontDeadStrip() const { return _dontDeadStrip; }
549 bool isThumb() const { return _thumb; }
550 bool isAlias() const { return _alias; }
551 Alignment alignment() const { return Alignment(_alignmentPowerOf2, _alignmentModulus); }
552 bool overridesDylibsWeakDef() const { return _overridesADylibsWeakDef; }
553 bool coalescedAway() const { return _coalescedAway; }
554 bool weakImported() const { return _weakImport; }
555 bool autoHide() const { return _autoHide; }
556 bool live() const { return _live; }
557 uint8_t machoSection() const { assert(_machoSection != 0); return _machoSection; }
558
559 void setScope(Scope s) { _scope = s; }
560 void setSymbolTableInclusion(SymbolTableInclusion i)
561 { _symbolTableInclusion = i; }
562 void setCombine(Combine c) { _combine = c; }
563 void setOverridesDylibsWeakDef() { _overridesADylibsWeakDef = true; }
564 void setCoalescedAway() { _coalescedAway = true; }
565 void setWeakImported() { _weakImport = true; assert(_definition == definitionProxy); }
566 void setAutoHide() { _autoHide = true; }
567 void setLive() { _live = true; }
568 void setLive(bool value) { _live = value; }
569 void setMachoSection(unsigned x) { assert(x != 0); assert(x < 256); _machoSection = x; }
570 void setSectionOffset(uint64_t o){ assert(_mode == modeSectionOffset); _address = o; _mode = modeSectionOffset; }
571 void setSectionStartAddress(uint64_t a) { assert(_mode == modeSectionOffset); _address += a; _mode = modeFinalAddress; }
572 uint64_t sectionOffset() const { assert(_mode == modeSectionOffset); return _address; }
573 uint64_t finalAddress() const { assert(_mode == modeFinalAddress); return _address; }
574
575 virtual const File* file() const = 0;
576 virtual bool translationUnitSource(const char** dir, const char** name) const = 0;
577 virtual const char* name() const = 0;
578 virtual uint64_t objectAddress() const = 0;
579 virtual uint64_t size() const = 0;
580 virtual void copyRawContent(uint8_t buffer[]) const = 0;
581 virtual const uint8_t* rawContentPointer() const { return NULL; }
582 virtual unsigned long contentHash(const class IndirectBindingTable&) const { return 0; }
583 virtual bool canCoalesceWith(const Atom& rhs, const class IndirectBindingTable&) const { return false; }
584 virtual Fixup::iterator fixupsBegin() const { return NULL; }
585 virtual Fixup::iterator fixupsEnd() const { return NULL; }
586 virtual UnwindInfo::iterator beginUnwind() const { return NULL; }
587 virtual UnwindInfo::iterator endUnwind() const { return NULL; }
588 virtual LineInfo::iterator beginLineInfo() const { return NULL; }
589 virtual LineInfo::iterator endLineInfo() const { return NULL; }
590
591 protected:
592 enum AddressMode { modeSectionOffset, modeFinalAddress };
593
594 void setAttributesFromAtom(const Atom& a) {
595 _section = a._section;
596 _alignmentModulus = a._alignmentModulus;
597 _alignmentPowerOf2 = a._alignmentPowerOf2;
598 _definition = a._definition;
599 _combine = a._combine;
600 _dontDeadStrip = a._dontDeadStrip;
601 _thumb = a._thumb;
602 _alias = a._alias;
603 _autoHide = a._autoHide;
604 _contentType = a._contentType;
605 _symbolTableInclusion = a._symbolTableInclusion;
606 _scope = a._scope;
607 _mode = a._mode;
608 _overridesADylibsWeakDef = a._overridesADylibsWeakDef;
609 _coalescedAway = a._coalescedAway;
610 _weakImport = a._weakImport;
611 }
612
613 const Section * _section;
614 uint64_t _address;
615 uint16_t _alignmentModulus;
616 uint8_t _alignmentPowerOf2;
617 Definition _definition : 2;
618 Combine _combine : 2;
619 bool _dontDeadStrip : 1;
620 bool _thumb : 1;
621 bool _alias : 1;
622 int _autoHide : 1;
623 ContentType _contentType : 5;
624 SymbolTableInclusion _symbolTableInclusion : 3;
625 Scope _scope : 2;
626 AddressMode _mode: 2;
627 bool _overridesADylibsWeakDef : 1;
628 bool _coalescedAway : 1;
629 bool _weakImport : 1;
630 bool _live : 1;
631 unsigned _machoSection : 8;
632 };
633
634
635 class IndirectBindingTable
636 {
637 public:
638 virtual const char* indirectName(uint32_t bindingIndex) const = 0;
639 virtual const ld::Atom* indirectAtom(uint32_t bindingIndex) const = 0;
640 };
641
642
643 class Internal
644 {
645 public:
646 class FinalSection : public ld::Section {
647 public:
648 FinalSection(const Section& sect) : Section(sect), address(0),
649 fileOffset(0), size(0), alignment(0),
650 indirectSymTabStartIndex(0), indirectSymTabElementSize(0),
651 relocStart(0), relocCount(0),
652 hasLocalRelocs(false), hasExternalRelocs(false) {}
653 std::vector<const Atom*> atoms;
654 uint64_t address;
655 uint64_t fileOffset;
656 uint64_t size;
657 uint32_t alignmentPaddingBytes;
658 uint8_t alignment;
659 uint32_t indirectSymTabStartIndex;
660 uint32_t indirectSymTabElementSize;
661 uint32_t relocStart;
662 uint32_t relocCount;
663 bool hasLocalRelocs;
664 bool hasExternalRelocs;
665 };
666
667 virtual ld::Internal::FinalSection* addAtom(const Atom&) = 0;
668 virtual ld::Internal::FinalSection* getFinalSection(const ld::Section& inputSection) = 0;
669 virtual ~Internal() {}
670 Internal() : bundleLoader(NULL),
671 entryPoint(NULL), classicBindingHelper(NULL),
672 lazyBindingHelper(NULL), compressedFastBinderProxy(NULL),
673 objcObjectConstraint(ld::File::objcConstraintNone),
674 objcDylibConstraint(ld::File::objcConstraintNone),
675 cpuSubType(0),
676 allObjectFilesScatterable(true), hasObjcReplacementClasses(false),
677 someObjectFileHasDwarf(false), usingHugeSections(false) { }
678
679 std::vector<FinalSection*> sections;
680 std::vector<ld::dylib::File*> dylibs;
681 std::vector<ld::relocatable::File::Stab> stabs;
682 std::vector<const ld::Atom*> indirectBindingTable;
683 const ld::dylib::File* bundleLoader;
684 const Atom* entryPoint;
685 const Atom* classicBindingHelper;
686 const Atom* lazyBindingHelper;
687 const Atom* compressedFastBinderProxy;
688 ld::File::ObjcConstraint objcObjectConstraint;
689 ld::File::ObjcConstraint objcDylibConstraint;
690 uint32_t cpuSubType;
691 bool allObjectFilesScatterable;
692 bool hasObjcReplacementClasses;
693 bool someObjectFileHasDwarf;
694 bool usingHugeSections;
695 };
696
697
698
699
700
701
702
703
704
705
706
707
708 } // namespace ld
709
710 #endif // __LD_HPP__