]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/ld.hpp
ld64-274.2.tar.gz
[apple/ld64.git] / src / ld / ld.hpp
index 42d5aa62713136f237a5a353a501dac87343956b..0db1b7e58d57e3f11549dd3a96b66590a8c65627 100644 (file)
 #include <unistd.h>
 #include <assert.h>
 
+#include <set>
+#include <map>
 #include <vector>
+#include <string>
 #include <unordered_set>
 
 #include "configure.h"
 
 namespace ld {
 
+// Forward declaration for bitcode support
+class Bitcode;
+
 //
 // ld::File 
 //
@@ -87,7 +93,7 @@ public:
                
                Ordinal (uint64_t ordinal) : _ordinal(ordinal) {}
                
-               enum { kArgListPartition=0, kIndirectDylibPartition=1, kLTOPartition = 2, kLinkerOptionPartition = 2, InvalidParition=0xffff };
+               enum { kArgListPartition=0, kIndirectDylibPartition=1, kLTOPartition = 2, kLinkerOptionPartition = 3, InvalidParition=0xffff };
                Ordinal(uint16_t partition, uint16_t majorIndex, uint16_t minorIndex, uint16_t counter) {
                        _ordinal = ((uint64_t)partition<<48) | ((uint64_t)majorIndex<<32) | ((uint64_t)minorIndex<<16) | ((uint64_t)counter<<0);
                }
@@ -96,14 +102,14 @@ public:
                const uint16_t  majorIndex() const              { return (_ordinal>>32)&0xffff; }
                const uint16_t  minorIndex() const              { return (_ordinal>>16)&0xffff; }
                const uint16_t  counter() const                 { return (_ordinal>>00)&0xffff; }
-               
+
                const Ordinal nextMajorIndex()          const { assert(majorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<32)); }
                const Ordinal nextMinorIndex()          const { assert(minorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<16)); }
                const Ordinal nextCounter()             const { assert(counter() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<0)); }
                
        public:
                Ordinal() : _ordinal(0) {};
-               
+
                static const Ordinal NullOrdinal()              { return Ordinal((uint64_t)0); }
                
                const bool validOrdinal() const { return _ordinal != 0; }
@@ -120,7 +126,7 @@ public:
                // Thus, an object pulled in from a .a that was listed in a file list could use all three fields.
                static const Ordinal makeArgOrdinal(uint16_t argIndex) { return Ordinal(kArgListPartition, argIndex, 0, 0); };
                const Ordinal nextFileListOrdinal() const { return nextMinorIndex(); }
-               const Ordinal archiveOrdinalWithMemberIndex(uint16_t index) const { return Ordinal(kArgListPartition, majorIndex(), minorIndex(), index); }
+               const Ordinal archiveOrdinalWithMemberIndex(uint16_t memberIndex) const { return Ordinal(partition(), majorIndex(), minorIndex(), memberIndex); }
                
                // For indirect libraries the partition is IndirectDylibPartition and the counter is used or order the libraries.
                static const ld::File::Ordinal indirectDylibBase() { return Ordinal(kIndirectDylibPartition, 0, 0, 0); }
@@ -131,8 +137,8 @@ public:
 
                // For linker options embedded in object files
                static const ld::File::Ordinal linkeOptionBase() { return Ordinal(kIndirectDylibPartition, 1, 0, 0); }
-               const Ordinal nextLinkerOptionOrdinal() { nextCounter(); return *this; };
-               
+               const Ordinal nextLinkerOptionOrdinal() { return nextCounter(); };
+
        };
        
        typedef enum { Reloc, Dylib, Archive, Other } Type;
@@ -146,10 +152,15 @@ public:
        virtual bool                                            forEachAtom(AtomHandler&) const = 0;
        virtual bool                                            justInTimeforEachAtom(const char* name, AtomHandler&) const = 0;
        virtual ObjcConstraint                          objCConstraint() const                  { return objcConstraintNone; }
+    virtual bool                                               objcHasCategoryClassPropertiesField() const { return false; }
+       virtual uint8_t                                         swiftVersion() const                    { return 0; }
        virtual uint32_t                                        cpuSubType() const              { return 0; }
        virtual uint32_t                                        subFileCount() const    { return 1; }
+       virtual uint32_t                                        minOSVersion() const    { return 0; }
+       virtual uint32_t                                        platformLoadCommand() const             { return 0; }
     bool                                                               fileExists() const     { return _modTime != 0; }
        Type                                                            type() const { return _type; }
+       virtual Bitcode*                                        getBitcode() const              { return NULL; }
 private:
        const char*                                                     _path;
        time_t                                                          _modTime;
@@ -163,11 +174,14 @@ private:
 //
 enum MacVersionMin { macVersionUnset=0, mac10_4=0x000A0400, mac10_5=0x000A0500, 
                                                mac10_6=0x000A0600, mac10_7=0x000A0700, mac10_8=0x000A0800,
-                                               mac10_9=0x000A0900, mac10_Future=0x10000000 };
+                                               mac10_9=0x000A0900, mac10_12=0x000A0C00, mac10_Future=0x10000000 };
 enum IOSVersionMin { iOSVersionUnset=0, iOS_2_0=0x00020000, iOS_3_1=0x00030100, 
                                                iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000,
-                                               iOS_6_0=0x00060000, iOS_7_0=0x00070000, iOS_Future=0x10000000};
+                                               iOS_6_0=0x00060000, iOS_7_0=0x00070000, iOS_8_0=0x00080000,
+                                               iOS_9_0=0x00090000, iOS_10_0=0x000A0000, iOS_Future=0x10000000};
+enum WatchOSVersionMin  { wOSVersionUnset=0, wOS_1_0=0x00010000, wOS_2_0=0x00020000 };
+
+
 namespace relocatable {
        //
        // ld::relocatable::File 
@@ -189,6 +203,7 @@ namespace relocatable {
        {
        public:
                enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 };
+               enum SourceKind { kSourceUnknown=0, kSourceObj, kSourceLTO, kSourceArchive, kSourceCompilerArchive };
                struct Stab {
                        const class Atom*       atom;
                        uint8_t                         type;
@@ -209,6 +224,7 @@ namespace relocatable {
                virtual bool                                            canScatterAtoms() const = 0;
                virtual bool                                            hasLongBranchStubs()            { return false; }
                virtual LinkerOptionsList*                      linkerOptions() const = 0;
+               virtual SourceKind                                      sourceKind() const { return kSourceUnknown; }
        };
 } // namespace relocatable
 
@@ -227,16 +243,17 @@ namespace dylib {
                {
                public:
                        virtual                         ~DylibHandler() {}
-                       virtual File*           findDylib(const char* installPath, const char* fromPath) = 0;
+                       virtual File*           findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative) = 0;
                };
                        
                                                                                        File(const char* pth, time_t modTime, Ordinal ord)
-                                                                                               : ld::File(pth, modTime, ord, Dylib), _dylibInstallPath(NULL),
+                                                                                               : ld::File(pth, modTime, ord, Dylib), _dylibInstallPath(NULL), _frameworkName(NULL),
                                                                                                _dylibTimeStamp(0), _dylibCurrentVersion(0), _dylibCompatibilityVersion(0),
-                                                                                               _explicitlyLinked(false), _implicitlyLinked(false),
+                                                                                               _explicitlyLinked(false), _implicitlyLinked(false), _speculativelyLoaded(false),
                                                                                                _lazyLoadedDylib(false), _forcedWeakLinked(false), _reExported(false),
                                                                                                _upward(false), _dead(false) { }
                                const char*                                     installPath() const                     { return _dylibInstallPath; }
+                               const char*                                     frameworkName() const           { return _frameworkName; }
                                uint32_t                                        timestamp() const                       { return _dylibTimeStamp; }
                                uint32_t                                        currentVersion() const          { return _dylibCurrentVersion; }
                                uint32_t                                        compatibilityVersion() const{ return _dylibCompatibilityVersion; }
@@ -244,7 +261,9 @@ namespace dylib {
                                bool                                            explicitlyLinked() const        { return _explicitlyLinked; }
                                void                                            setImplicitlyLinked()           { _implicitlyLinked = true; }
                                bool                                            implicitlyLinked() const        { return _implicitlyLinked; }
-                               
+                               void                                            setSpeculativelyLoaded()        { _speculativelyLoaded = true; }
+                               bool                                            speculativelyLoaded() const     { return _speculativelyLoaded; }
+
                                // attributes of how dylib will be used when linked
                                void                                            setWillBeLazyLoadedDylb()               { _lazyLoadedDylib = true; }
                                bool                                            willBeLazyLoadedDylib() const   { return _lazyLoadedDylib; }
@@ -262,20 +281,24 @@ namespace dylib {
                virtual bool                                            providedExportAtom() const = 0;
                virtual const char*                                     parentUmbrella() const = 0;
                virtual const std::vector<const char*>* allowableClients() const = 0;
+               virtual const std::vector<const char*>& rpaths() 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;
-               virtual const void*                                     codeSignatureDR() const = 0;
                virtual bool                                            installPathVersionSpecific() const { return false; }
-       protected:
+               virtual bool                                            appExtensionSafe() const = 0;
+
+       public:
                const char*                                                     _dylibInstallPath;
+               const char*                                                     _frameworkName;
                uint32_t                                                        _dylibTimeStamp;
                uint32_t                                                        _dylibCurrentVersion;
                uint32_t                                                        _dylibCompatibilityVersion;
                bool                                                            _explicitlyLinked;
                bool                                                            _implicitlyLinked;
+               bool                                                            _speculativelyLoaded;
                bool                                                            _lazyLoadedDylib;
                bool                                                            _forcedWeakLinked;
                bool                                                            _reExported;
@@ -309,14 +332,14 @@ class Section
 {
 public:
        enum Type { typeUnclassified, typeCode, typePageZero, typeImportProxies, typeLinkEdit, typeMachHeader, typeStack,
-                               typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO, 
+                               typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO, typeTempAlias,
                                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 };
+                               typeFirstSection, typeLastSection, typeDebug, typeSectCreate };
 
 
                                        Section(const char* sgName, const char* sctName,
@@ -409,6 +432,7 @@ struct Fixup
                                        kindStoreARM64GOTLoadPage21, kindStoreARM64GOTLoadPageOff12,
                                        kindStoreARM64GOTLeaPage21, kindStoreARM64GOTLeaPageOff12,
                                        kindStoreARM64TLVPLoadPage21, kindStoreARM64TLVPLoadPageOff12,
+                                       kindStoreARM64TLVPLoadNowLeaPage21, kindStoreARM64TLVPLoadNowLeaPageOff12,
                                        kindStoreARM64PointerToGOT, kindStoreARM64PCRelToGOT,
 #endif
                                        // dtrace probes
@@ -419,9 +443,13 @@ struct Fixup
                                        kindStoreThumbDtraceCallSiteNop, kindStoreThumbDtraceIsEnableSiteClear,
                                        // lazy binding
                                        kindLazyTarget, kindSetLazyOffset,
+                                       // islands
+                                       kindIslandTarget,
                                        // data-in-code markers
                                        kindDataInCodeStartData, kindDataInCodeStartJT8, kindDataInCodeStartJT16, 
                                        kindDataInCodeStartJT32, kindDataInCodeStartJTA32, kindDataInCodeEnd,
+                                       // linker optimization hints
+                                       kindLinkerOptimizationHint,
                                        // pointer store combinations
                                        kindStoreTargetAddressLittleEndian32,   // kindSetTargetAddress + kindStoreLittleEndian32
                                        kindStoreTargetAddressLittleEndian64,   // kindSetTargetAddress + kindStoreLittleEndian64
@@ -451,6 +479,10 @@ struct Fixup
                                        kindStoreTargetAddressARM64GOTLoadPageOff12,// kindSetTargetAddress + kindStoreARM64GOTLoadPageOff12
                                        kindStoreTargetAddressARM64GOTLeaPage21,        // kindSetTargetAddress + kindStoreARM64GOTLeaPage21
                                        kindStoreTargetAddressARM64GOTLeaPageOff12,     // kindSetTargetAddress + kindStoreARM64GOTLeaPageOff12
+                                       kindStoreTargetAddressARM64TLVPLoadPage21,      // kindSetTargetAddress + kindStoreARM64TLVPLoadPage21
+                                       kindStoreTargetAddressARM64TLVPLoadPageOff12,// kindSetTargetAddress + kindStoreARM64TLVPLoadPageOff12
+                                       kindStoreTargetAddressARM64TLVPLoadNowLeaPage21,        // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPage21
+                                       kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12,     // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPageOff12
 #endif
                        };
 
@@ -516,6 +548,21 @@ struct Fixup
                contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) 
                        { u.addend = addend; }
                        
+       Fixup(Kind k, uint32_t lohKind, uint32_t off1, uint32_t off2) :
+               offsetInAtom(off1), kind(k), clusterSize(k1of1),  
+               weakImport(false), binding(Fixup::bindingNone), contentAddendOnly(false), 
+               contentDetlaToAddendOnly(false), contentIgnoresAddend(false) {
+                       assert(k == kindLinkerOptimizationHint);
+                       LOH_arm64 extra;
+                       extra.addend = 0;
+                       extra.info.kind = lohKind;
+                       extra.info.count = 1;
+                       extra.info.delta1 = 0;
+                       extra.info.delta2 = (off2 - off1) >> 2;
+                       u.addend = extra.addend; 
+               }
+                       
+
        bool firstInCluster() const { 
                switch (clusterSize) {
                        case k1of1:
@@ -544,6 +591,18 @@ struct Fixup
                return false;
        }
        
+       union LOH_arm64 {
+               uint64_t        addend;
+               struct {
+                       unsigned        kind    :  6,
+                                               count   :  2,   // 00 => 1 addr, 11 => 4 addrs
+                                               delta1 : 14,    // 16-bit delta, low 2 bits assumed zero
+                                               delta2 : 14,
+                                               delta3 : 14,
+                                               delta4 : 14;    
+               } info;
+       };
+       
 };
 
 //
@@ -602,7 +661,7 @@ public:
                                        typeSectionEnd, typeBranchIsland, typeLazyPointer, typeStub, typeNonLazyPointer, 
                                        typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
                                        typeLTOtemporary, typeResolver,
-                                       typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers };
+                                       typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers, typeTLVPointer };
 
        enum SymbolTableInclusion { symbolTableNotIn, symbolTableNotInFinalLinkedImages, symbolTableIn,
                                                                symbolTableInAndNeverStrip, symbolTableInAsAbsolute, 
@@ -637,7 +696,8 @@ public:
                                                                                                        _contentType(ct), _symbolTableInclusion(i),
                                                                                                        _scope(s), _mode(modeSectionOffset), 
                                                                                                        _overridesADylibsWeakDef(false), _coalescedAway(false),
-                                                                                                       _live(false), _machoSection(0), _weakImportState(weakImportUnset)
+                                                                                                       _live(false), _dontDeadStripIfRefLive(false),
+                                                                                                       _machoSection(0), _weakImportState(weakImportUnset)
                                                                                                         {
                                                                                                        #ifndef NDEBUG
                                                                                                                switch ( _combine ) {
@@ -661,6 +721,7 @@ public:
        ContentType                                                             contentType() const                     { return _contentType; }
        SymbolTableInclusion                                    symbolTableInclusion() const{ return _symbolTableInclusion; }
        bool                                                                    dontDeadStrip() const           { return _dontDeadStrip; }
+       bool                                                                    dontDeadStripIfReferencesLive() const { return _dontDeadStripIfRefLive; }
        bool                                                                    isThumb() const                         { return _thumb; }
        bool                                                                    isAlias() const                         { return _alias; }
        Alignment                                                               alignment() const                       { return Alignment(_alignmentPowerOf2, _alignmentModulus); }
@@ -680,6 +741,7 @@ public:
        void                                                                    setCoalescedAway()                      { _coalescedAway = true; }
        void                                                                    setWeakImportState(bool w)      { assert(_definition == definitionProxy); _weakImportState = ( w ? weakImportTrue : weakImportFalse); }
        void                                                                    setAutoHide()                           { _autoHide = true; }
+       void                                                                    setDontDeadStripIfReferencesLive() { _dontDeadStripIfRefLive = true; }
        void                                                                    setLive()                                       { _live = true; }
        void                                                                    setLive(bool value)                     { _live = value; }
        void                                                                    setMachoSection(unsigned x) { assert(x != 0); assert(x < 256); _machoSection = x; }
@@ -691,6 +753,9 @@ public:
        bool                                                                    finalAddressMode() const    { return (_mode == modeFinalAddress); }
 #endif
        virtual const File*                                             file() const = 0;
+       // Return the original file this atom belongs to, for instance for an LTO atom,
+       // file() would return the LTO MachO file instead of the original bitcode file.
+       virtual const ld::File*                             originalFile() const       { return file(); }
        virtual const char*                                             translationUnitSource() const { return NULL; }
        virtual const char*                                             name() const = 0;
        virtual uint64_t                                                objectAddress() const = 0;
@@ -707,15 +772,13 @@ public:
                }
                return false;
        }
+       virtual void                                                    setFile(const File* f)          { }
        
        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;
@@ -734,6 +797,9 @@ protected:
                                                                                                        _weakImportState = a._weakImportState;
                                                                                                }
 
+protected:
+       enum AddressMode { modeSectionOffset, modeFinalAddress };
+
        const Section *                                         _section;
        uint64_t                                                        _address;
        uint16_t                                                        _alignmentModulus;
@@ -751,6 +817,7 @@ protected:
        bool                                                            _overridesADylibsWeakDef : 1;
        bool                                                            _coalescedAway : 1;
        bool                                                            _live : 1;
+       bool                                                            _dontDeadStripIfRefLive : 1;
        unsigned                                                        _machoSection : 8;
        WeakImportState                                         _weakImportState : 2;
 };
@@ -781,6 +848,7 @@ struct CStringEquals
 
 typedef        std::unordered_set<const char*, ld::CStringHash, ld::CStringEquals>  CStringSet;
 
+
 class Internal
 {
 public:
@@ -805,7 +873,10 @@ public:
                bool                                                    hasExternalRelocs;
        };
        
+       typedef std::map<const ld::Atom*, FinalSection*>        AtomToSection;          
 
+       virtual uint64_t                                        assignFileOffsets() = 0;
+       virtual void                                            setSectionSizesAndAlignments() = 0;
        virtual ld::Internal::FinalSection*     addAtom(const Atom&) = 0;
        virtual ld::Internal::FinalSection* getFinalSection(const ld::Section& inputSection) = 0;
        virtual                                                         ~Internal() {}
@@ -814,16 +885,28 @@ public:
                                                                                        lazyBindingHelper(NULL), compressedFastBinderProxy(NULL),
                                                                                        objcObjectConstraint(ld::File::objcConstraintNone), 
                                                                                        objcDylibConstraint(ld::File::objcConstraintNone), 
-                                                                                       cpuSubType(0), 
+                                                                                       swiftVersion(0), cpuSubType(0), minOSVersion(0),
+                                                                                       objectFileFoundWithNoVersion(false),
                                                                                        allObjectFilesScatterable(true), 
-                                                                                       someObjectFileHasDwarf(false), usingHugeSections(false) { }
-                                                                               
+                                                                                       someObjectFileHasDwarf(false), usingHugeSections(false),
+                                                                                       hasThreadLocalVariableDefinitions(false),
+                                                                                       hasWeakExternalSymbols(false),
+                                                                                       someObjectHasOptimizationHints(false),
+                                                                                       dropAllBitcode(false), embedMarkerOnly(false)   { }
+
        std::vector<FinalSection*>                                      sections;
        std::vector<ld::dylib::File*>                           dylibs;
+       std::vector<std::string>                                        archivePaths;
        std::vector<ld::relocatable::File::Stab>        stabs;
+       AtomToSection                                                           atomToSection;          
+       CStringSet                                                                      unprocessedLinkerOptionLibraries;
+       CStringSet                                                                      unprocessedLinkerOptionFrameworks;
        CStringSet                                                                      linkerOptionLibraries;
        CStringSet                                                                      linkerOptionFrameworks;
        std::vector<const ld::Atom*>                            indirectBindingTable;
+       std::vector<const ld::relocatable::File*>       filesWithBitcode;
+       std::vector<const ld::Atom*>                            deadAtoms;
+       std::unordered_set<const char*>                         allUndefProxies;
        const ld::dylib::File*                                          bundleLoader;
        const Atom*                                                                     entryPoint;
        const Atom*                                                                     classicBindingHelper;
@@ -831,10 +914,20 @@ public:
        const Atom*                                                                     compressedFastBinderProxy;
        ld::File::ObjcConstraint                                        objcObjectConstraint;
        ld::File::ObjcConstraint                                        objcDylibConstraint;
+       uint8_t                                                                         swiftVersion;
        uint32_t                                                                        cpuSubType;
+       uint32_t                                                                        minOSVersion;
+       uint32_t                                                                        derivedPlatformLoadCommand;
+       bool                                                                            objectFileFoundWithNoVersion;
        bool                                                                            allObjectFilesScatterable;
        bool                                                                            someObjectFileHasDwarf;
        bool                                                                            usingHugeSections;
+       bool                                                                            hasThreadLocalVariableDefinitions;
+       bool                                                                            hasWeakExternalSymbols;
+       bool                                                                            someObjectHasOptimizationHints;
+       bool                                                                            dropAllBitcode;
+       bool                                                                            embedMarkerOnly;
+       std::vector<std::string>                                        ltoBitcodePath;
 };
 
 
@@ -843,10 +936,6 @@ public:
 
 
 
-
-
-
-
 } // namespace ld 
 
 #endif // __LD_HPP__