]> 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 96075a7398967a98c9447c8b47af804d0fa3b238..0db1b7e58d57e3f11549dd3a96b66590a8c65627 100644 (file)
 #include <unistd.h>
 #include <assert.h>
 
-#include <vector>
 #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 
 //
@@ -51,7 +58,9 @@ namespace ld {
 class File
 {
 public:
-       enum ObjcConstraint { objcConstraintNone, objcConstraintRetainRelease, objcConstraintRetainReleaseOrGC, objcConstraintGC };
+       enum ObjcConstraint { objcConstraintNone, objcConstraintRetainRelease, 
+                                                       objcConstraintRetainReleaseOrGC, objcConstraintGC,
+                                                       objcConstraintRetainReleaseForSimulator };
        
        class AtomHandler {
        public:
@@ -60,21 +69,103 @@ public:
                virtual void            doFile(const class File&) = 0;
        };
 
-                                                                               File(const char* pth, time_t modTime, uint32_t ord)
-                                                                                       : _path(pth), _modTime(modTime), _ordinal(ord) { }
+       //
+       // ld::File::Ordinal 
+       //
+       // Codifies the rules of ordering input files for symbol precedence. These are:
+       // - Input files listed on the command line are ordered according to their index in the argument list.
+       // - Input files listed in a file list are ordered first at the index of the file list argument, then
+       //   by index in the file list
+       // - Input files extracted from archives are ordered using the ordinal of the archive itself plus the
+       //   index of the object file within the archive
+       // - Indirect dylibs are ordered after all input files derived from the command line, in the order that
+       //   they are discovered.
+       // - The LTO object file is last.
+       //
+       class Ordinal
+       {
+       private:
+               // The actual numeric ordinal. Lower values have higher precedence and a zero value is invalid.
+               // The 64 bit ordinal is broken into 4 16 bit chunks. The high 16 bits are a "partition" that
+               // is used to distinguish major ordinal groups: command line, indirect dylib, LTO.
+               // The remaining chunks are used according to the partition (see below).
+               uint64_t        _ordinal;
+               
+               Ordinal (uint64_t ordinal) : _ordinal(ordinal) {}
+               
+               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);
+               }
+               
+               const uint16_t  partition() const               { return (_ordinal>>48)&0xffff; }
+               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; }
+               
+               bool operator ==(const Ordinal& rhs) const { return _ordinal == rhs._ordinal; }
+               bool operator !=(const Ordinal& rhs) const {    return _ordinal != rhs._ordinal; }
+               bool operator < (const Ordinal& rhs) const { return _ordinal < rhs._ordinal; }
+               bool operator > (const Ordinal& rhs) const { return _ordinal > rhs._ordinal; }
+               
+               // For ordinals derived from the command line args the partition is ArgListPartition
+               // The majorIndex is the arg index that pulls in the file, file list, or archive.
+               // The minorIndex is used for files pulled in by a file list and the value is the index of the file in the file list.
+               // The counter is used for .a files and the value is the index of the object in the archive.
+               // 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 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); }
+               const Ordinal nextIndirectDylibOrdinal() const { return nextCounter(); }
+               
+               // For the LTO mach-o the partition is LTOPartition. As there is only one LTO file no other fields are needed.
+               static const ld::File::Ordinal LTOOrdinal()                     { return Ordinal(kLTOPartition, 0, 0, 0); }
+
+               // For linker options embedded in object files
+               static const ld::File::Ordinal linkeOptionBase() { return Ordinal(kIndirectDylibPartition, 1, 0, 0); }
+               const Ordinal nextLinkerOptionOrdinal() { return nextCounter(); };
+
+       };
+       
+       typedef enum { Reloc, Dylib, Archive, Other } Type;
+       
+                                                                               File(const char* pth, time_t modTime, Ordinal ord, Type type)
+                                                                                       : _path(pth), _modTime(modTime), _ordinal(ord), _type(type) { }
        virtual                                                         ~File() {}
                        const char*                                     path() const                    { return _path; }
                        time_t                                          modificationTime() const{ return _modTime; }
-                       uint32_t                                        ordinal() const                 { return _ordinal; }
+       Ordinal                                                         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 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;
-       uint32_t                                                        _ordinal;
+       const Ordinal                                           _ordinal;
+       const Type                                                      _type;
 };
 
 
@@ -82,18 +173,21 @@ private:
 // minumum OS versions
 //
 enum MacVersionMin { macVersionUnset=0, mac10_4=0x000A0400, mac10_5=0x000A0500, 
-                                               mac10_6=0x000A0600, mac10_7=0x000A0700 };
+                                               mac10_6=0x000A0600, mac10_7=0x000A0700, mac10_8=0x000A0800,
+                                               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_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000,
+                                               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 
        //
        // 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
@@ -109,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;
@@ -117,17 +212,19 @@ namespace relocatable {
                        uint32_t                        value;
                        const char*                     string;
                };
+               typedef const std::vector< std::vector<const char*> > LinkerOptionsList;
 
-                                                                                       File(const char* pth, time_t modTime, uint32_t ord)
-                                                                                               : ld::File(pth, modTime, ord) { }
+                                                                                       File(const char* pth, time_t modTime, Ordinal ord)
+                                                                                               : ld::File(pth, modTime, ord, Reloc) { }
                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; }
+               virtual LinkerOptionsList*                      linkerOptions() const = 0;
+               virtual SourceKind                                      sourceKind() const { return kSourceUnknown; }
        };
 } // namespace relocatable
 
@@ -146,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, uint32_t ord)
-                                                                                               : ld::File(pth, modTime, ord), _dylibInstallPath(NULL),
+                                                                                       File(const char* pth, time_t modTime, Ordinal ord)
+                                                                                               : 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; }
@@ -163,6 +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; }
@@ -180,18 +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;
-       protected:
+               virtual bool                                            installPathVersionSpecific() const { return false; }
+               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;
@@ -210,8 +317,8 @@ namespace archive {
        class File : public ld::File
        {
        public:
-                                                                                       File(const char* pth, time_t modTime, uint32_t ord)
-                                                                                               : ld::File(pth, modTime, ord) { }
+                                                                                       File(const char* pth, time_t modTime, Ordinal ord)
+                                                                                               : ld::File(pth, modTime, ord, Archive) { }
                virtual                                                         ~File() {}
                virtual bool                                            justInTimeDataOnlyforEachAtom(const char* name, AtomHandler&) const = 0;
        };
@@ -225,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,
@@ -318,18 +425,31 @@ struct Fixup
                                        kindStoreARMLoad12,
                                        kindStoreARMLow16, kindStoreARMHigh16, 
                                        kindStoreThumbLow16, kindStoreThumbHigh16, 
-                                       // PowerPC specific store kinds
-                                       kindStorePPCBranch24, kindStorePPCBranch14,
-                                       kindStorePPCPicLow14, kindStorePPCPicLow16, kindStorePPCPicHigh16AddLow, 
-                                       kindStorePPCAbsLow14, kindStorePPCAbsLow16, kindStorePPCAbsHigh16AddLow, kindStorePPCAbsHigh16, 
+#if SUPPORT_ARCH_arm64
+                                       // ARM64 specific store kinds
+                                       kindStoreARM64Branch26,  
+                                       kindStoreARM64Page21, kindStoreARM64PageOff12,
+                                       kindStoreARM64GOTLoadPage21, kindStoreARM64GOTLoadPageOff12,
+                                       kindStoreARM64GOTLeaPage21, kindStoreARM64GOTLeaPageOff12,
+                                       kindStoreARM64TLVPLoadPage21, kindStoreARM64TLVPLoadPageOff12,
+                                       kindStoreARM64TLVPLoadNowLeaPage21, kindStoreARM64TLVPLoadNowLeaPageOff12,
+                                       kindStoreARM64PointerToGOT, kindStoreARM64PCRelToGOT,
+#endif
                                        // dtrace probes
                                        kindDtraceExtra,
                                        kindStoreX86DtraceCallSiteNop, kindStoreX86DtraceIsEnableSiteClear,
                                        kindStoreARMDtraceCallSiteNop, kindStoreARMDtraceIsEnableSiteClear,
+                                       kindStoreARM64DtraceCallSiteNop, kindStoreARM64DtraceIsEnableSiteClear,
                                        kindStoreThumbDtraceCallSiteNop, kindStoreThumbDtraceIsEnableSiteClear,
-                                       kindStorePPCDtraceCallSiteNop, kindStorePPCDtraceIsEnableSiteClear,
                                        // 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
@@ -350,8 +470,20 @@ struct Fixup
                                        kindStoreTargetAddressARMBranch24,              // kindSetTargetAddress + kindStoreARMBranch24
                                        kindStoreTargetAddressThumbBranch22,    // kindSetTargetAddress + kindStoreThumbBranch22
                                        kindStoreTargetAddressARMLoad12,                // kindSetTargetAddress + kindStoreARMLoad12
-                                       // PowerPC value calculation and store combinations
-                                       kindStoreTargetAddressPPCBranch24,              // kindSetTargetAddress + kindStorePPCBranch24
+#if SUPPORT_ARCH_arm64
+                                       // ARM64 value calculation and store combinations
+                                       kindStoreTargetAddressARM64Branch26,            // kindSetTargetAddress + kindStoreARM64Branch26
+                                       kindStoreTargetAddressARM64Page21,                      // kindSetTargetAddress + kindStoreARM64Page21
+                                       kindStoreTargetAddressARM64PageOff12,           // kindSetTargetAddress + kindStoreARM64PageOff12
+                                       kindStoreTargetAddressARM64GOTLoadPage21,       // kindSetTargetAddress + kindStoreARM64GOTLoadPage21
+                                       kindStoreTargetAddressARM64GOTLoadPageOff12,// kindSetTargetAddress + kindStoreARM64GOTLoadPageOff12
+                                       kindStoreTargetAddressARM64GOTLeaPage21,        // kindSetTargetAddress + kindStoreARM64GOTLeaPage21
+                                       kindStoreTargetAddressARM64GOTLeaPageOff12,     // kindSetTargetAddress + kindStoreARM64GOTLeaPageOff12
+                                       kindStoreTargetAddressARM64TLVPLoadPage21,      // kindSetTargetAddress + kindStoreARM64TLVPLoadPage21
+                                       kindStoreTargetAddressARM64TLVPLoadPageOff12,// kindSetTargetAddress + kindStoreARM64TLVPLoadPageOff12
+                                       kindStoreTargetAddressARM64TLVPLoadNowLeaPage21,        // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPage21
+                                       kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12,     // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPageOff12
+#endif
                        };
 
        union {
@@ -367,54 +499,70 @@ struct Fixup
        TargetBinding   binding : 3;
        bool                    contentAddendOnly : 1;
        bool                    contentDetlaToAddendOnly : 1;
+       bool                    contentIgnoresAddend : 1;
        
        typedef Fixup*          iterator;
 
        Fixup() :
                offsetInAtom(0), kind(kindNone), clusterSize(k1of1), weakImport(false), 
                binding(bindingNone),  
-               contentAddendOnly(false), contentDetlaToAddendOnly(false) { u.target = NULL; }
+               contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) { u.target = NULL; }
 
        Fixup(Kind k, Atom* targetAtom) :
                offsetInAtom(0), kind(k), clusterSize(k1of1), weakImport(false), 
                binding(Fixup::bindingDirectlyBound),  
-               contentAddendOnly(false), contentDetlaToAddendOnly(false)  
+               contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(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)  
+               contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(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) 
+               contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(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) 
+               contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(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) 
+               contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(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) 
+               contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(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) 
+               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:
@@ -443,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;
+       };
+       
 };
 
 //
@@ -501,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, 
@@ -536,13 +696,14 @@ 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 ) {
                                                                                                                        case combineByNameAndContent:
                                                                                                                        case combineByNameAndReferences:
-                                                                                                                               assert(_symbolTableInclusion == symbolTableNotIn);
+                                                                                                                               assert(_symbolTableInclusion != symbolTableIn);
                                                                                                                                assert(_scope != scopeGlobal);
                                                                 break;
                                                             case combineByName:
@@ -560,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); }
@@ -579,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; }
@@ -586,9 +749,14 @@ public:
        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; }
-
+#ifndef NDEBUG
+       bool                                                                    finalAddressMode() const    { return (_mode == modeFinalAddress); }
+#endif
        virtual const File*                                             file() const = 0;
-       virtual bool                                                    translationUnitSource(const char** dir, const char** name) 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;
        virtual uint64_t                                                size() const = 0;
@@ -598,14 +766,19 @@ public:
        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; }
+       bool                                                                    hasFixupsOfKind(Fixup::Kind kind) const {
+               for (ld::Fixup::iterator fit = fixupsBegin(), end=fixupsEnd(); fit != end; ++fit) {
+                       if ( fit->kind == kind ) return true;
+               }
+               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;
@@ -614,7 +787,6 @@ protected:
                                                                                                        _combine = a._combine;
                                                                                                        _dontDeadStrip = a._dontDeadStrip;
                                                                                                        _thumb = a._thumb;
-                                                                                                       _alias = a._alias;
                                                                                                        _autoHide = a._autoHide;
                                                                                                        _contentType = a._contentType;
                                                                                                        _symbolTableInclusion = a._symbolTableInclusion;
@@ -625,6 +797,9 @@ protected:
                                                                                                        _weakImportState = a._weakImportState;
                                                                                                }
 
+protected:
+       enum AddressMode { modeSectionOffset, modeFinalAddress };
+
        const Section *                                         _section;
        uint64_t                                                        _address;
        uint16_t                                                        _alignmentModulus;
@@ -642,6 +817,7 @@ protected:
        bool                                                            _overridesADylibsWeakDef : 1;
        bool                                                            _coalescedAway : 1;
        bool                                                            _live : 1;
+       bool                                                            _dontDeadStripIfRefLive : 1;
        unsigned                                                        _machoSection : 8;
        WeakImportState                                         _weakImportState : 2;
 };
@@ -655,6 +831,24 @@ public:
 };
 
 
+       
+// utility classes for using std::unordered_map with c-strings
+struct CStringHash {
+       size_t operator()(const char* __s) const {
+               size_t __h = 0;
+               for ( ; *__s; ++__s)
+                       __h = 5 * __h + *__s;
+               return __h;
+       };
+};
+struct CStringEquals
+{
+       bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
+};
+
+typedef        std::unordered_set<const char*, ld::CStringHash, ld::CStringEquals>  CStringSet;
+
+
 class Internal
 {
 public:
@@ -679,6 +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() {}
@@ -687,14 +885,28 @@ public:
                                                                                        lazyBindingHelper(NULL), compressedFastBinderProxy(NULL),
                                                                                        objcObjectConstraint(ld::File::objcConstraintNone), 
                                                                                        objcDylibConstraint(ld::File::objcConstraintNone), 
-                                                                                       cpuSubType(0), 
-                                                                                       allObjectFilesScatterable(true), hasObjcReplacementClasses(false),
-                                                                                       someObjectFileHasDwarf(false), usingHugeSections(false) { }
-                                                                               
+                                                                                       swiftVersion(0), cpuSubType(0), minOSVersion(0),
+                                                                                       objectFileFoundWithNoVersion(false),
+                                                                                       allObjectFilesScatterable(true), 
+                                                                                       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;
@@ -702,11 +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                                                                            hasObjcReplacementClasses;
        bool                                                                            someObjectFileHasDwarf;
        bool                                                                            usingHugeSections;
+       bool                                                                            hasThreadLocalVariableDefinitions;
+       bool                                                                            hasWeakExternalSymbols;
+       bool                                                                            someObjectHasOptimizationHints;
+       bool                                                                            dropAllBitcode;
+       bool                                                                            embedMarkerOnly;
+       std::vector<std::string>                                        ltoBitcodePath;
 };
 
 
@@ -715,11 +936,6 @@ public:
 
 
 
-
-
-
-
-
 } // namespace ld 
 
 #endif // __LD_HPP__