/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- * * Copyright (c) 2005-2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef __LD_HPP__ #define __LD_HPP__ #include <stdint.h> #include <math.h> #include <unistd.h> #include <assert.h> #include <vector> #include <set> namespace ld { // // ld::File // // Abstract base class for all object or library files the linker processes. // // forEachAtom() iterates over the Atoms in the order they occur in the file. // // justInTimeforEachAtom(name) iterates over lazily created Atoms. For instance if // File is a static library, justInTimeforEachAtom() will iterate over the base set // of Atoms from the archive member implementing 'name'. // class File { public: enum ObjcConstraint { objcConstraintNone, objcConstraintRetainRelease, objcConstraintRetainReleaseOrGC, objcConstraintGC }; class AtomHandler { public: virtual ~AtomHandler() {} virtual void doAtom(const class Atom&) = 0; virtual void doFile(const class File&) = 0; }; File(const char* pth, time_t modTime, uint32_t ord) : _path(pth), _modTime(modTime), _ordinal(ord) { } virtual ~File() {} const char* path() const { return _path; } time_t modificationTime() const{ return _modTime; } uint32_t ordinal() const { return _ordinal; } virtual bool forEachAtom(AtomHandler&) const = 0; virtual bool justInTimeforEachAtom(const char* name, AtomHandler&) const = 0; virtual ObjcConstraint objCConstraint() const { return objcConstraintNone; } virtual uint32_t cpuSubType() const { return 0; } virtual uint32_t subFileCount() const { return 1; } private: const char* _path; time_t _modTime; uint32_t _ordinal; }; // // minumum OS versions // enum MacVersionMin { macVersionUnset=0, mac10_4=0x000A0400, mac10_5=0x000A0500, mac10_6=0x000A0600, mac10_7=0x000A0700 }; enum IOSVersionMin { iOSVersionUnset=0, iOS_2_0=0x00020000, iOS_3_1=0x00030100, iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000 }; namespace relocatable { // // ld::relocatable::File // // Abstract base class for object files the linker processes. // // objcReplacementClasses() is reflects if the file was compiled for fix-and-continue // // debugInfo() returns if the object file contains debugger information (stabs or dwarf). // // stabs() lazily creates a vector of Stab objects for each atom // // canScatterAtoms() true for all compiler generated code. Hand written assembly can opt-in // via .subsections_via_symbols directive. When true it means the linker can break up section // content at symbol boundaries and do optimizations like coalescing, dead code stripping, or // apply order files. // // optimize() used by libLTO to lazily generate code from llvm bit-code files // class File : public ld::File { public: enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 }; struct Stab { const class Atom* atom; uint8_t type; uint8_t other; uint16_t desc; uint32_t value; const char* string; }; File(const char* pth, time_t modTime, uint32_t ord) : ld::File(pth, modTime, ord) { } virtual ~File() {} virtual bool objcReplacementClasses() const = 0; virtual DebugInfoKind debugInfo() const = 0; virtual const char* debugInfoPath() const { return path(); } virtual time_t debugInfoModificationTime() const { return modificationTime(); } virtual const std::vector<Stab>* stabs() const = 0; virtual bool canScatterAtoms() const = 0; virtual bool hasLongBranchStubs() { return false; } }; } // namespace relocatable namespace dylib { // // ld::dylib::File // // Abstract base class for dynamic shared libraries read by the linker processes. // class File : public ld::File { public: class DylibHandler { public: virtual ~DylibHandler() {} virtual File* findDylib(const char* installPath, const char* fromPath) = 0; }; File(const char* pth, time_t modTime, uint32_t ord) : ld::File(pth, modTime, ord), _dylibInstallPath(NULL), _dylibTimeStamp(0), _dylibCurrentVersion(0), _dylibCompatibilityVersion(0), _explicitlyLinked(false), _implicitlyLinked(false), _lazyLoadedDylib(false), _forcedWeakLinked(false), _reExported(false), _upward(false), _dead(false) { } const char* installPath() const { return _dylibInstallPath; } uint32_t timestamp() const { return _dylibTimeStamp; } uint32_t currentVersion() const { return _dylibCurrentVersion; } uint32_t compatibilityVersion() const{ return _dylibCompatibilityVersion; } void setExplicitlyLinked() { _explicitlyLinked = true; } bool explicitlyLinked() const { return _explicitlyLinked; } void setImplicitlyLinked() { _implicitlyLinked = true; } bool implicitlyLinked() const { return _implicitlyLinked; } // attributes of how dylib will be used when linked void setWillBeLazyLoadedDylb() { _lazyLoadedDylib = true; } bool willBeLazyLoadedDylib() const { return _lazyLoadedDylib; } void setForcedWeakLinked() { _forcedWeakLinked = true; } bool forcedWeakLinked() const { return _forcedWeakLinked; } void setWillBeReExported() { _reExported = true; } bool willBeReExported() const { return _reExported; } void setWillBeUpwardDylib() { _upward = true; } bool willBeUpwardDylib() const { return _upward; } void setWillBeRemoved(bool value) { _dead = value; } bool willRemoved() const { return _dead; } virtual void processIndirectLibraries(DylibHandler* handler, bool addImplicitDylibs) = 0; virtual bool providedExportAtom() const = 0; virtual const char* parentUmbrella() const = 0; virtual const std::vector<const char*>* allowableClients() const = 0; virtual bool hasWeakExternals() const = 0; virtual bool deadStrippable() const = 0; virtual bool hasWeakDefinition(const char* name) const = 0; virtual bool hasPublicInstallName() const = 0; virtual bool allSymbolsAreWeakImported() const = 0; protected: const char* _dylibInstallPath; uint32_t _dylibTimeStamp; uint32_t _dylibCurrentVersion; uint32_t _dylibCompatibilityVersion; bool _explicitlyLinked; bool _implicitlyLinked; bool _lazyLoadedDylib; bool _forcedWeakLinked; bool _reExported; bool _upward; bool _dead; }; } // namespace dylib namespace archive { // // ld::archive::File // // Abstract base class for static libraries read by the linker processes. // class File : public ld::File { public: File(const char* pth, time_t modTime, uint32_t ord) : ld::File(pth, modTime, ord) { } virtual ~File() {} virtual bool justInTimeDataOnlyforEachAtom(const char* name, AtomHandler&) const = 0; }; } // namespace archive // // ld::Section // class Section { public: enum Type { typeUnclassified, typeCode, typePageZero, typeImportProxies, typeLinkEdit, typeMachHeader, typeStack, typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO, typeCString, typeNonStdCString, typeCStringPointer, typeUTF16Strings, typeCFString, typeObjC1Classes, typeCFI, typeLSDA, typeDtraceDOF, typeUnwindInfo, typeObjCClassRefs, typeObjC2CategoryList, typeZeroFill, typeTentativeDefs, typeLazyPointer, typeStub, typeNonLazyPointer, typeDyldInfo, typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers, typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols, typeTLVDefs, typeTLVZeroFill, typeTLVInitialValues, typeTLVInitializerPointers, typeTLVPointers, typeFirstSection, typeLastSection, typeDebug }; Section(const char* sgName, const char* sctName, Type t, bool hidden=false) : _segmentName(sgName), _sectionName(sctName), _type(t), _hidden(hidden) {} Section(const Section& sect) : _segmentName(sect.segmentName()), _sectionName(sect.sectionName()), _type(sect.type()), _hidden(sect.isSectionHidden()) {} bool operator==(const Section& rhs) const { return ( (_hidden==rhs._hidden) && (strcmp(_segmentName, rhs._segmentName)==0) && (strcmp(_sectionName, rhs._sectionName)==0) ); } bool operator!=(const Section& rhs) const { return ! (*this == rhs); } const char* segmentName() const { return _segmentName; } const char* sectionName() const { return _sectionName; } Type type() const { return _type; } bool isSectionHidden() const { return _hidden; } private: const char* _segmentName; const char* _sectionName; Type _type; bool _hidden; }; // // ld::Fixup // // A Fixup describes how part of an Atom's content must be fixed up. For instance, // an instruction may contain a displacement to another Atom that must be // fixed up by the linker. // // A Fixup my reference another Atom. There are two kinds of references: direct and by-name. // With a direct reference, the target is bound by the File that created it. // For instance a reference to a static would produce a direct reference. // A by-name reference requires the linker to find the target Atom with the // required name in order to be bound. // // For a link to succeed all Fixup must be bound. // // A Reference also has a fix-up-offset. This is the offset into the content of the // Atom holding the reference where the fix-up (relocation) will be applied. // // struct Fixup { enum TargetBinding { bindingNone, bindingByNameUnbound, bindingDirectlyBound, bindingByContentBound, bindingsIndirectlyBound }; enum Cluster { k1of1, k1of2, k2of2, k1of3, k2of3, k3of3, k1of4, k2of4, k3of4, k4of4, k1of5, k2of5, k3of5, k4of5, k5of5 }; enum Kind { kindNone, kindNoneFollowOn, // grouping kindNoneGroupSubordinate, kindNoneGroupSubordinateFDE, kindNoneGroupSubordinateLSDA, kindNoneGroupSubordinatePersonality, // value calculations kindSetTargetAddress, kindSubtractTargetAddress, kindAddAddend, kindSubtractAddend, kindSetTargetImageOffset, kindSetTargetSectionOffset, kindSetTargetTLVTemplateOffset, // pointer store kinds (of current calculated value) kindStore8, kindStoreLittleEndian16, kindStoreLittleEndianLow24of32, kindStoreLittleEndian32, kindStoreLittleEndian64, kindStoreBigEndian16, kindStoreBigEndianLow24of32, kindStoreBigEndian32, kindStoreBigEndian64, // Intel specific store kinds kindStoreX86BranchPCRel8, kindStoreX86BranchPCRel32, kindStoreX86PCRel8, kindStoreX86PCRel16, kindStoreX86PCRel32, kindStoreX86PCRel32_1, kindStoreX86PCRel32_2, kindStoreX86PCRel32_4, kindStoreX86PCRel32GOTLoad, kindStoreX86PCRel32GOTLoadNowLEA, kindStoreX86PCRel32GOT, kindStoreX86PCRel32TLVLoad, kindStoreX86PCRel32TLVLoadNowLEA, kindStoreX86Abs32TLVLoad, kindStoreX86Abs32TLVLoadNowLEA, // ARM specific store kinds kindStoreARMBranch24, kindStoreThumbBranch22, kindStoreARMLoad12, kindStoreARMLow16, kindStoreARMHigh16, kindStoreThumbLow16, kindStoreThumbHigh16, // dtrace probes kindDtraceExtra, kindStoreX86DtraceCallSiteNop, kindStoreX86DtraceIsEnableSiteClear, kindStoreARMDtraceCallSiteNop, kindStoreARMDtraceIsEnableSiteClear, kindStoreThumbDtraceCallSiteNop, kindStoreThumbDtraceIsEnableSiteClear, // lazy binding kindLazyTarget, kindSetLazyOffset, // pointer store combinations kindStoreTargetAddressLittleEndian32, // kindSetTargetAddress + kindStoreLittleEndian32 kindStoreTargetAddressLittleEndian64, // kindSetTargetAddress + kindStoreLittleEndian64 kindStoreTargetAddressBigEndian32, // kindSetTargetAddress + kindStoreBigEndian32 kindStoreTargetAddressBigEndian64, // kindSetTargetAddress + kindStoreBigEndian364 kindSetTargetTLVTemplateOffsetLittleEndian32, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian32 kindSetTargetTLVTemplateOffsetLittleEndian64, // kindSetTargetTLVTemplateOffset + kindStoreLittleEndian64 // Intel value calculation and store combinations kindStoreTargetAddressX86PCRel32, // kindSetTargetAddress + kindStoreX86PCRel32 kindStoreTargetAddressX86BranchPCRel32, // kindSetTargetAddress + kindStoreX86BranchPCRel32 kindStoreTargetAddressX86PCRel32GOTLoad,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoad kindStoreTargetAddressX86PCRel32GOTLoadNowLEA,// kindSetTargetAddress + kindStoreX86PCRel32GOTLoadNowLEA kindStoreTargetAddressX86PCRel32TLVLoad, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoad kindStoreTargetAddressX86PCRel32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86PCRel32TLVLoadNowLEA kindStoreTargetAddressX86Abs32TLVLoad, // kindSetTargetAddress + kindStoreX86Abs32TLVLoad kindStoreTargetAddressX86Abs32TLVLoadNowLEA, // kindSetTargetAddress + kindStoreX86Abs32TLVLoadNowLEA // ARM value calculation and store combinations kindStoreTargetAddressARMBranch24, // kindSetTargetAddress + kindStoreARMBranch24 kindStoreTargetAddressThumbBranch22, // kindSetTargetAddress + kindStoreThumbBranch22 kindStoreTargetAddressARMLoad12, // kindSetTargetAddress + kindStoreARMLoad12 }; union { const Atom* target; const char* name; uint64_t addend; uint32_t bindingIndex; } u; uint32_t offsetInAtom; Kind kind : 8; Cluster clusterSize : 4; bool weakImport : 1; TargetBinding binding : 3; bool contentAddendOnly : 1; bool contentDetlaToAddendOnly : 1; typedef Fixup* iterator; Fixup() : offsetInAtom(0), kind(kindNone), clusterSize(k1of1), weakImport(false), binding(bindingNone), contentAddendOnly(false), contentDetlaToAddendOnly(false) { u.target = NULL; } Fixup(Kind k, Atom* targetAtom) : offsetInAtom(0), kind(k), clusterSize(k1of1), weakImport(false), binding(Fixup::bindingDirectlyBound), contentAddendOnly(false), contentDetlaToAddendOnly(false) { assert(targetAtom != NULL); u.target = targetAtom; } Fixup(uint32_t off, Cluster c, Kind k) : offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(Fixup::bindingNone), contentAddendOnly(false), contentDetlaToAddendOnly(false) { u.addend = 0; } Fixup(uint32_t off, Cluster c, Kind k, bool weakIm, const char* name) : offsetInAtom(off), kind(k), clusterSize(c), weakImport(weakIm), binding(Fixup::bindingByNameUnbound), contentAddendOnly(false), contentDetlaToAddendOnly(false) { assert(name != NULL); u.name = name; } Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const char* name) : offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b), contentAddendOnly(false), contentDetlaToAddendOnly(false) { assert(name != NULL); u.name = name; } Fixup(uint32_t off, Cluster c, Kind k, const Atom* targetAtom) : offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(Fixup::bindingDirectlyBound), contentAddendOnly(false), contentDetlaToAddendOnly(false) { assert(targetAtom != NULL); u.target = targetAtom; } Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const Atom* targetAtom) : offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b), contentAddendOnly(false), contentDetlaToAddendOnly(false) { assert(targetAtom != NULL); u.target = targetAtom; } Fixup(uint32_t off, Cluster c, Kind k, uint64_t addend) : offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(Fixup::bindingNone), contentAddendOnly(false), contentDetlaToAddendOnly(false) { u.addend = addend; } bool firstInCluster() const { switch (clusterSize) { case k1of1: case k1of2: case k1of3: case k1of4: case k1of5: return true; default: break; } return false; } bool lastInCluster() const { switch (clusterSize) { case k1of1: case k2of2: case k3of3: case k4of4: case k5of5: return true; default: break; } return false; } }; // // ld::Atom // // An atom is the fundamental unit of linking. A C function or global variable is an atom. // An atom has content and attributes. The content of a function atom is the instructions // that implement the function. The content of a global variable atom is its initial bits. // // Name: // The name of an atom is the label name generated by the compiler. A C compiler names foo() // as _foo. A C++ compiler names foo() as __Z3foov. // The name refers to the first byte of the content. An atom cannot have multiple entry points. // Such code is modeled as multiple atoms, each having a "follow on" reference to the next. // A "follow on" reference is a contraint to the linker to the atoms must be laid out contiguously. // // Scope: // An atom is in one of three scopes: translation-unit, linkage-unit, or global. These correspond // to the C visibility of static, hidden, default. // // DefinitionKind: // An atom is one of five defintion kinds: // regular Most atoms. // weak C++ compiler makes some functions weak if there might be multiple copies // that the linker needs to coalesce. // tentative A straggler from ancient C when the extern did not exist. "int foo;" is ambiguous. // It could be a prototype or it could be a definition. // external This is a "proxy" atom produced by a dylib reader. It has no content. It exists // so that the graph of Atoms can be complete. // external-weak Same as external, but the definition in the dylib is weak. // // SymbolTableInclusion: // An atom may or may not be in the symbol table in an object file. // in Most atoms for functions or global data // not-in Anonymous atoms such literal c-strings, or other compiler generated data // not-in-final Atom whose name should not be in the symbol table of final linkd image (e.g. 'l' labels .eh labels) // in-never-strip Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o) // // ContentType: // Some atoms require specially processing by the linker based on their content. For instance, zero-fill data // atom are group together at the end of the DATA segment to reduce disk size. // // ObjectAddress: // For reproducability, the linker lays out atoms in the order they occurred in the source (object) files. // The objectAddress() method returns the address of an atom in the object file so that the linker // can arrange the atoms. // // class Atom { public: enum Scope { scopeTranslationUnit, scopeLinkageUnit, scopeGlobal }; enum Definition { definitionRegular, definitionTentative, definitionAbsolute, definitionProxy }; enum Combine { combineNever, combineByName, combineByNameAndContent, combineByNameAndReferences }; enum ContentType { typeUnclassified, typeZeroFill, typeCString, typeCFI, typeLSDA, typeSectionStart, typeSectionEnd, typeBranchIsland, typeLazyPointer, typeStub, typeNonLazyPointer, typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers, typeLTOtemporary, typeResolver, typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers }; enum SymbolTableInclusion { symbolTableNotIn, symbolTableNotInFinalLinkedImages, symbolTableIn, symbolTableInAndNeverStrip, symbolTableInAsAbsolute, symbolTableInWithRandomAutoStripLabel }; enum WeakImportState { weakImportUnset, weakImportTrue, weakImportFalse }; struct Alignment { Alignment(int p2, int m=0) : powerOf2(p2), modulus(m) {} uint8_t trailingZeros() const { return (modulus==0) ? powerOf2 : __builtin_ctz(modulus); } uint16_t powerOf2; uint16_t modulus; }; struct LineInfo { const char* fileName; uint32_t atomOffset; uint32_t lineNumber; typedef LineInfo* iterator; }; struct UnwindInfo { uint32_t startOffset; uint32_t unwindInfo; typedef UnwindInfo* iterator; }; Atom(const Section& sect, Definition d, Combine c, Scope s, ContentType ct, SymbolTableInclusion i, bool dds, bool thumb, bool al, Alignment a) : _section(§), _address(0), _alignmentModulus(a.modulus), _alignmentPowerOf2(a.powerOf2), _definition(d), _combine(c), _dontDeadStrip(dds), _thumb(thumb), _alias(al), _autoHide(false), _contentType(ct), _symbolTableInclusion(i), _scope(s), _mode(modeSectionOffset), _overridesADylibsWeakDef(false), _coalescedAway(false), _live(false), _machoSection(0), _weakImportState(weakImportUnset) { #ifndef NDEBUG switch ( _combine ) { case combineByNameAndContent: case combineByNameAndReferences: assert(_symbolTableInclusion == symbolTableNotIn); assert(_scope != scopeGlobal); break; case combineByName: case combineNever: break; }; #endif } virtual ~Atom() {} const Section& section() const { return *_section; } Definition definition() const { return _definition; } Combine combine() const { return _combine; } Scope scope() const { return _scope; } ContentType contentType() const { return _contentType; } SymbolTableInclusion symbolTableInclusion() const{ return _symbolTableInclusion; } bool dontDeadStrip() const { return _dontDeadStrip; } bool isThumb() const { return _thumb; } bool isAlias() const { return _alias; } Alignment alignment() const { return Alignment(_alignmentPowerOf2, _alignmentModulus); } bool overridesDylibsWeakDef() const { return _overridesADylibsWeakDef; } bool coalescedAway() const { return _coalescedAway; } bool weakImported() const { return _weakImportState == weakImportTrue; } WeakImportState weakImportState() const { return _weakImportState; } bool autoHide() const { return _autoHide; } bool live() const { return _live; } uint8_t machoSection() const { assert(_machoSection != 0); return _machoSection; } void setScope(Scope s) { _scope = s; } void setSymbolTableInclusion(SymbolTableInclusion i) { _symbolTableInclusion = i; } void setCombine(Combine c) { _combine = c; } void setOverridesDylibsWeakDef() { _overridesADylibsWeakDef = true; } void setCoalescedAway() { _coalescedAway = true; } void setWeakImportState(bool w) { assert(_definition == definitionProxy); _weakImportState = ( w ? weakImportTrue : weakImportFalse); } void setAutoHide() { _autoHide = true; } void setLive() { _live = true; } void setLive(bool value) { _live = value; } void setMachoSection(unsigned x) { assert(x != 0); assert(x < 256); _machoSection = x; } void setSectionOffset(uint64_t o){ assert(_mode == modeSectionOffset); _address = o; _mode = modeSectionOffset; } void setSectionStartAddress(uint64_t a) { assert(_mode == modeSectionOffset); _address += a; _mode = modeFinalAddress; } uint64_t sectionOffset() const { assert(_mode == modeSectionOffset); return _address; } uint64_t finalAddress() const { assert(_mode == modeFinalAddress); return _address; } virtual const File* file() const = 0; virtual bool translationUnitSource(const char** dir, const char** name) const = 0; virtual const char* name() const = 0; virtual uint64_t objectAddress() const = 0; virtual uint64_t size() const = 0; virtual void copyRawContent(uint8_t buffer[]) const = 0; virtual const uint8_t* rawContentPointer() const { return NULL; } virtual unsigned long contentHash(const class IndirectBindingTable&) const { return 0; } virtual bool canCoalesceWith(const Atom& rhs, const class IndirectBindingTable&) const { return false; } virtual Fixup::iterator fixupsBegin() const { return NULL; } virtual Fixup::iterator fixupsEnd() const { return NULL; } virtual UnwindInfo::iterator beginUnwind() const { return NULL; } virtual UnwindInfo::iterator endUnwind() const { return NULL; } virtual LineInfo::iterator beginLineInfo() const { return NULL; } virtual LineInfo::iterator endLineInfo() const { return NULL; } protected: enum AddressMode { modeSectionOffset, modeFinalAddress }; void setAttributesFromAtom(const Atom& a) { _section = a._section; _alignmentModulus = a._alignmentModulus; _alignmentPowerOf2 = a._alignmentPowerOf2; _definition = a._definition; _combine = a._combine; _dontDeadStrip = a._dontDeadStrip; _thumb = a._thumb; _alias = a._alias; _autoHide = a._autoHide; _contentType = a._contentType; _symbolTableInclusion = a._symbolTableInclusion; _scope = a._scope; _mode = a._mode; _overridesADylibsWeakDef = a._overridesADylibsWeakDef; _coalescedAway = a._coalescedAway; _weakImportState = a._weakImportState; } const Section * _section; uint64_t _address; uint16_t _alignmentModulus; uint8_t _alignmentPowerOf2; Definition _definition : 2; Combine _combine : 2; bool _dontDeadStrip : 1; bool _thumb : 1; bool _alias : 1; int _autoHide : 1; ContentType _contentType : 5; SymbolTableInclusion _symbolTableInclusion : 3; Scope _scope : 2; AddressMode _mode: 2; bool _overridesADylibsWeakDef : 1; bool _coalescedAway : 1; bool _live : 1; unsigned _machoSection : 8; WeakImportState _weakImportState : 2; }; class IndirectBindingTable { public: virtual const char* indirectName(uint32_t bindingIndex) const = 0; virtual const ld::Atom* indirectAtom(uint32_t bindingIndex) const = 0; }; class Internal { public: class FinalSection : public ld::Section { public: FinalSection(const Section& sect) : Section(sect), address(0), fileOffset(0), size(0), alignment(0), indirectSymTabStartIndex(0), indirectSymTabElementSize(0), relocStart(0), relocCount(0), hasLocalRelocs(false), hasExternalRelocs(false) {} std::vector<const Atom*> atoms; uint64_t address; uint64_t fileOffset; uint64_t size; uint32_t alignmentPaddingBytes; uint8_t alignment; uint32_t indirectSymTabStartIndex; uint32_t indirectSymTabElementSize; uint32_t relocStart; uint32_t relocCount; bool hasLocalRelocs; bool hasExternalRelocs; }; virtual ld::Internal::FinalSection* addAtom(const Atom&) = 0; virtual ld::Internal::FinalSection* getFinalSection(const ld::Section& inputSection) = 0; virtual ~Internal() {} Internal() : bundleLoader(NULL), entryPoint(NULL), classicBindingHelper(NULL), lazyBindingHelper(NULL), compressedFastBinderProxy(NULL), objcObjectConstraint(ld::File::objcConstraintNone), objcDylibConstraint(ld::File::objcConstraintNone), cpuSubType(0), allObjectFilesScatterable(true), hasObjcReplacementClasses(false), someObjectFileHasDwarf(false), usingHugeSections(false) { } std::vector<FinalSection*> sections; std::vector<ld::dylib::File*> dylibs; std::vector<ld::relocatable::File::Stab> stabs; std::vector<const ld::Atom*> indirectBindingTable; const ld::dylib::File* bundleLoader; const Atom* entryPoint; const Atom* classicBindingHelper; const Atom* lazyBindingHelper; const Atom* compressedFastBinderProxy; ld::File::ObjcConstraint objcObjectConstraint; ld::File::ObjcConstraint objcDylibConstraint; uint32_t cpuSubType; bool allObjectFilesScatterable; bool hasObjcReplacementClasses; bool someObjectFileHasDwarf; bool usingHugeSections; }; } // namespace ld #endif // __LD_HPP__