]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/HeaderAndLoadCommands.hpp
ld64-302.3.1.tar.gz
[apple/ld64.git] / src / ld / HeaderAndLoadCommands.hpp
index 35daef1de569ce2bba0da10190b3132bef5db4cd..fbcc13fe7c4ceb35d34eed24896decce70671dfa 100644 (file)
@@ -49,6 +49,12 @@ public:
 
        virtual void setUUID(const uint8_t digest[16]) = 0;
        virtual void recopyUUIDCommand() = 0;
 
        virtual void setUUID(const uint8_t digest[16]) = 0;
        virtual void recopyUUIDCommand() = 0;
+       virtual const uint8_t* getUUID() const = 0;
+       virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd,
+                                                                         uint64_t& sectOffset, uint64_t& sectEnd) const = 0;
+       virtual void linkeditCmdInfo(uint64_t& offset, uint64_t& size) const = 0;
+       virtual void symbolTableCmdInfo(uint64_t& offset, uint64_t& size) const = 0;
+
 };
 
 template <typename A>
 };
 
 template <typename A>
@@ -68,7 +74,13 @@ public:
        // overrides of HeaderAndLoadCommandsAbtract
        virtual void setUUID(const uint8_t digest[16])  { memcpy(_uuid, digest, 16); }
        virtual void recopyUUIDCommand();
        // overrides of HeaderAndLoadCommandsAbtract
        virtual void setUUID(const uint8_t digest[16])  { memcpy(_uuid, digest, 16); }
        virtual void recopyUUIDCommand();
-       
+       virtual const uint8_t* getUUID() const                          { return &_uuid[0]; }
+       virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd,
+                                                                         uint64_t& sectOffset, uint64_t& sectEnd) const;
+       virtual void linkeditCmdInfo(uint64_t& offset, uint64_t& size) const;
+       virtual void symbolTableCmdInfo(uint64_t& offset, uint64_t& size) const;
+
+
 private:
        typedef typename A::P                                           P;
        typedef typename A::P::E                                        E;
 private:
        typedef typename A::P                                           P;
        typedef typename A::P::E                                        E;
@@ -85,15 +97,16 @@ private:
        uint32_t                                        commandsCount() const;
        uint32_t                                        threadLoadCommandSize() const;
        uint8_t*                                        copySingleSegmentLoadCommand(uint8_t* p) const;
        uint32_t                                        commandsCount() const;
        uint32_t                                        threadLoadCommandSize() const;
        uint8_t*                                        copySingleSegmentLoadCommand(uint8_t* p) const;
-       uint8_t*                                        copySegmentLoadCommands(uint8_t* p) const;
+       uint8_t*                                        copySegmentLoadCommands(uint8_t* p, uint8_t* base) const;
        uint8_t*                                        copyDyldInfoLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDyldInfoLoadCommand(uint8_t* p) const;
-       uint8_t*                                        copySymbolTableLoadCommand(uint8_t* p) const;
+       uint8_t*                                        copySymbolTableLoadCommand(uint8_t* p, uint8_t* base) const;
        uint8_t*                                        copyDynamicSymbolTableLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDyldLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDylibIDLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyRoutinesLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyUUIDLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyVersionLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDynamicSymbolTableLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDyldLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDylibIDLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyRoutinesLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyUUIDLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyVersionLoadCommand(uint8_t* p) const;
+       uint8_t*                                        copyBuildVersionLoadCommand(uint8_t* p) const;
        uint8_t*                                        copySourceVersionLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyThreadsLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyEntryPointLoadCommand(uint8_t* p) const;
        uint8_t*                                        copySourceVersionLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyThreadsLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyEntryPointLoadCommand(uint8_t* p) const;
@@ -107,9 +120,9 @@ private:
        uint8_t*                                        copySubUmbrellaLoadCommand(uint8_t* p, const char* name) const;
        uint8_t*                                        copyFunctionStartsLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDataInCodeLoadCommand(uint8_t* p) const;
        uint8_t*                                        copySubUmbrellaLoadCommand(uint8_t* p, const char* name) const;
        uint8_t*                                        copyFunctionStartsLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDataInCodeLoadCommand(uint8_t* p) const;
-       uint8_t*                                        copyDependentDRLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDyldEnvLoadCommand(uint8_t* p, const char* env) const;
        uint8_t*                                        copyLinkerOptionsLoadCommand(uint8_t* p, const std::vector<const char*>&) const;
        uint8_t*                                        copyDyldEnvLoadCommand(uint8_t* p, const char* env) const;
        uint8_t*                                        copyLinkerOptionsLoadCommand(uint8_t* p, const std::vector<const char*>&) const;
+       uint8_t*                                        copyOptimizationHintsLoadCommand(uint8_t* p) const;
 
        uint32_t                                        sectionFlags(ld::Internal::FinalSection* sect) const;
        bool                                            sectionTakesNoDiskSpace(ld::Internal::FinalSection* sect) const;
 
        uint32_t                                        sectionFlags(ld::Internal::FinalSection* sect) const;
        bool                                            sectionTakesNoDiskSpace(ld::Internal::FinalSection* sect) const;
@@ -133,10 +146,12 @@ private:
        bool                                            _hasRPathLoadCommands;
        bool                                            _hasSubFrameworkLoadCommand;
        bool                                            _hasVersionLoadCommand;
        bool                                            _hasRPathLoadCommands;
        bool                                            _hasSubFrameworkLoadCommand;
        bool                                            _hasVersionLoadCommand;
+       bool                                            _hasBuildVersionLoadCommand;
        bool                                            _hasFunctionStartsLoadCommand;
        bool                                            _hasDataInCodeLoadCommand;
        bool                                            _hasSourceVersionLoadCommand;
        bool                                            _hasFunctionStartsLoadCommand;
        bool                                            _hasDataInCodeLoadCommand;
        bool                                            _hasSourceVersionLoadCommand;
-       bool                                            _hasDependentDRInfo;
+       bool                                            _hasOptimizationHints;
+       Options::Platform                       _platform;
        uint32_t                                        _dylibLoadCommmandsCount;
        uint32_t                                        _allowableClientLoadCommmandsCount;
        uint32_t                                        _dyldEnvironExrasCount;
        uint32_t                                        _dylibLoadCommmandsCount;
        uint32_t                                        _allowableClientLoadCommmandsCount;
        uint32_t                                        _dyldEnvironExrasCount;
@@ -144,7 +159,10 @@ private:
        std::vector<const char*>        _subUmbrellaNames;
        uint8_t                                         _uuid[16];
        mutable macho_uuid_command<P>*  _uuidCmdInOutputBuffer;
        std::vector<const char*>        _subUmbrellaNames;
        uint8_t                                         _uuid[16];
        mutable macho_uuid_command<P>*  _uuidCmdInOutputBuffer;
+       mutable uint32_t                        _linkeditCmdOffset;
+       mutable uint32_t                        _symboltableCmdOffset;
        std::vector< std::vector<const char*> >  _linkerOptions;
        std::vector< std::vector<const char*> >  _linkerOptions;
+       std::unordered_set<uint64_t>&   _toolsVersions;
        
        static ld::Section                      _s_section;
        static ld::Section                      _s_preload_section;
        
        static ld::Section                      _s_section;
        static ld::Section                      _s_preload_section;
@@ -162,8 +180,9 @@ HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld:
                                ld::Atom::definitionRegular, ld::Atom::combineNever, 
                                ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, 
                                ld::Atom::symbolTableNotIn, false, false, false, 
                                ld::Atom::definitionRegular, ld::Atom::combineNever, 
                                ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, 
                                ld::Atom::symbolTableNotIn, false, false, false, 
-                               (opts.outputKind() == Options::kPreload) ? ld::Atom::Alignment(0) : ld::Atom::Alignment(12) ), 
-               _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL)
+                               (opts.outputKind() == Options::kPreload) ? ld::Atom::Alignment(0) : ld::Atom::Alignment(log2(opts.segmentAlignment())) ),
+               _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL), _linkeditCmdOffset(0), _symboltableCmdOffset(0),
+               _toolsVersions(state.toolsVersions)
 {
        bzero(_uuid, 16);
        _hasDyldInfoLoadCommand = opts.makeCompressedDyldInfo();
 {
        bzero(_uuid, 16);
        _hasDyldInfoLoadCommand = opts.makeCompressedDyldInfo();
@@ -176,6 +195,7 @@ HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld:
        _hasRoutinesLoadCommand = (opts.initFunctionName() != NULL);
        _hasSymbolTableLoadCommand = true;
        _hasUUIDLoadCommand = (opts.UUIDMode() != Options::kUUIDNone);
        _hasRoutinesLoadCommand = (opts.initFunctionName() != NULL);
        _hasSymbolTableLoadCommand = true;
        _hasUUIDLoadCommand = (opts.UUIDMode() != Options::kUUIDNone);
+       _hasOptimizationHints = (_state.someObjectHasOptimizationHints && (opts.outputKind() == Options::kObjectFile));
        switch ( opts.outputKind() ) {
                case Options::kDynamicExecutable:
                case Options::kDynamicLibrary:
        switch ( opts.outputKind() ) {
                case Options::kDynamicExecutable:
                case Options::kDynamicLibrary:
@@ -194,15 +214,13 @@ HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld:
                                        break;
                                }
                        }
                                        break;
                                }
                        }
-                       for (CStringSet::const_iterator it = _state.linkerOptionFrameworks.begin(); it != _state.linkerOptionFrameworks.end(); ++it) {
-                               const char* frameWorkName = *it;
+                       for (const char* frameworkName : _state.unprocessedLinkerOptionFrameworks) {
                                std::vector<const char*>* lo = new std::vector<const char*>();
                                lo->push_back("-framework");
                                std::vector<const char*>* lo = new std::vector<const char*>();
                                lo->push_back("-framework");
-                               lo->push_back(frameWorkName);
+                               lo->push_back(frameworkName);
                                _linkerOptions.push_back(*lo);
                        };
                                _linkerOptions.push_back(*lo);
                        };
-                       for (CStringSet::const_iterator it = _state.linkerOptionLibraries.begin(); it != _state.linkerOptionLibraries.end(); ++it) {
-                               const char* libName = *it;
+                       for (const char* libName : _state.unprocessedLinkerOptionLibraries) {
                                std::vector<const char*>* lo = new std::vector<const char*>();
                                char * s = new char[strlen(libName)+3];
                                strcpy(s, "-l");
                                std::vector<const char*>* lo = new std::vector<const char*>();
                                char * s = new char[strlen(libName)+3];
                                strcpy(s, "-l");
@@ -220,11 +238,24 @@ HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld:
        }
        _hasRPathLoadCommands = (_options.rpaths().size() != 0);
        _hasSubFrameworkLoadCommand = (_options.umbrellaName() != NULL);
        }
        _hasRPathLoadCommands = (_options.rpaths().size() != 0);
        _hasSubFrameworkLoadCommand = (_options.umbrellaName() != NULL);
-       _hasVersionLoadCommand = _options.addVersionLoadCommand();
+       _platform = _options.platform();
+       if ( (_platform == Options::kPlatformUnknown) && (_state.derivedPlatform != 0) )
+               _platform = (Options::Platform)_state.derivedPlatform;
+       if ( _options.addVersionLoadCommand() ) {
+               _hasBuildVersionLoadCommand = _options.addBuildVersionLoadCommand();
+               _hasVersionLoadCommand = !_hasBuildVersionLoadCommand;
+       }
+       else if (((_options.outputKind() == Options::kObjectFile) && (_platform != Options::kPlatformUnknown) && !state.objectFileFoundWithNoVersion) ) {
+               _hasBuildVersionLoadCommand = (_platform == Options::kPlatform_bridgeOS);
+               _hasVersionLoadCommand = !_hasBuildVersionLoadCommand;
+       }
+       else {
+               _hasVersionLoadCommand = false;
+               _hasBuildVersionLoadCommand = false;
+       }
        _hasFunctionStartsLoadCommand = _options.addFunctionStarts();
        _hasDataInCodeLoadCommand = _options.addDataInCodeInfo();
        _hasSourceVersionLoadCommand = _options.needsSourceVersionLoadCommand();
        _hasFunctionStartsLoadCommand = _options.addFunctionStarts();
        _hasDataInCodeLoadCommand = _options.addDataInCodeInfo();
        _hasSourceVersionLoadCommand = _options.needsSourceVersionLoadCommand();
-       _hasDependentDRInfo = _options.needsDependentDRInfo();
        _dylibLoadCommmandsCount = _writer.dylibCount();
        _allowableClientLoadCommmandsCount = _options.allowableClients().size();
        _dyldEnvironExrasCount = _options.dyldEnvironExtras().size();
        _dylibLoadCommmandsCount = _writer.dylibCount();
        _allowableClientLoadCommmandsCount = _options.allowableClients().size();
        _dyldEnvironExrasCount = _options.dyldEnvironExtras().size();
@@ -323,6 +354,46 @@ unsigned int HeaderAndLoadCommandsAtom<A>::segmentCount() const
        return count;
 }
 
        return count;
 }
 
+template <typename A>
+bool HeaderAndLoadCommandsAtom<A>::bitcodeBundleCommand(uint64_t &cmdOffset, uint64_t &cmdEnd,
+                                                                                                               uint64_t &sectOffset, uint64_t &sectEnd) const
+{
+       if ( _options.outputKind() == Options::kObjectFile ) {
+               return false;
+       }
+       cmdOffset = sizeof(macho_header<P>);
+       const char* lastSegName = "";
+       for (std::vector<ld::Internal::FinalSection*>::iterator it = _state.sections.begin(); it != _state.sections.end(); ++it) {
+               if ( strcmp(lastSegName, (*it)->segmentName()) != 0 ) {
+                       lastSegName = (*it)->segmentName();
+                       cmdOffset += sizeof(macho_segment_command<P>);
+               }
+               if ( strcmp((*it)->segmentName(), "__LLVM") == 0 && strcmp((*it)->sectionName(), "__bundle") == 0 ) {
+                       sectOffset = (*it)->fileOffset;
+                       sectEnd = (*(it + 1))->fileOffset;
+                       cmdEnd = cmdOffset + sizeof(macho_section<P>);
+                       return true;
+               }
+               if ( ! (*it)->isSectionHidden() )
+                       cmdOffset += sizeof(macho_section<P>);
+       }
+       return false;
+}
+
+template <typename A>
+void HeaderAndLoadCommandsAtom<A>::linkeditCmdInfo(uint64_t &offset, uint64_t &size) const
+{
+       offset = _linkeditCmdOffset;
+       size = sizeof(macho_segment_command<P>);
+}
+
+template <typename A>
+void HeaderAndLoadCommandsAtom<A>::symbolTableCmdInfo(uint64_t &offset, uint64_t &size) const
+{
+       offset = _symboltableCmdOffset;
+       size = sizeof(macho_symtab_command<P>);
+}
+
 
 template <typename A>
 uint64_t HeaderAndLoadCommandsAtom<A>::size() const
 
 template <typename A>
 uint64_t HeaderAndLoadCommandsAtom<A>::size() const
@@ -356,6 +427,9 @@ uint64_t HeaderAndLoadCommandsAtom<A>::size() const
        if ( _hasVersionLoadCommand )
                sz += sizeof(macho_version_min_command<P>);
        
        if ( _hasVersionLoadCommand )
                sz += sizeof(macho_version_min_command<P>);
        
+       if ( _hasBuildVersionLoadCommand )
+               sz += alignedSize(sizeof(macho_build_version_command<P>) + sizeof(macho_build_tool_version<P>)*_toolsVersions.size());
+       
        if ( _hasSourceVersionLoadCommand )
                sz += sizeof(macho_source_version_command<P>);
                
        if ( _hasSourceVersionLoadCommand )
                sz += sizeof(macho_source_version_command<P>);
                
@@ -424,7 +498,7 @@ uint64_t HeaderAndLoadCommandsAtom<A>::size() const
                }
        }
        
                }
        }
        
-       if ( _hasDependentDRInfo ) 
+       if ( _hasOptimizationHints )
                sz += sizeof(macho_linkedit_data_command<P>);
                
        return sz;
                sz += sizeof(macho_linkedit_data_command<P>);
                
        return sz;
@@ -459,6 +533,9 @@ uint32_t HeaderAndLoadCommandsAtom<A>::commandsCount() const
        if ( _hasVersionLoadCommand )
                ++count;
 
        if ( _hasVersionLoadCommand )
                ++count;
 
+       if ( _hasBuildVersionLoadCommand )
+               ++count;
+       
        if ( _hasSourceVersionLoadCommand )
                ++count;
                
        if ( _hasSourceVersionLoadCommand )
                ++count;
                
@@ -501,7 +578,7 @@ uint32_t HeaderAndLoadCommandsAtom<A>::commandsCount() const
                }
        }
 
                }
        }
 
-       if ( _hasDependentDRInfo ) 
+       if ( _hasOptimizationHints )
                ++count;
                
        return count;
                ++count;
                
        return count;
@@ -561,9 +638,9 @@ uint32_t HeaderAndLoadCommandsAtom<A>::flags() const
                                        bits |= MH_FORCE_FLAT;
                                        break;
                        }
                                        bits |= MH_FORCE_FLAT;
                                        break;
                        }
-                       if ( _writer.hasWeakExternalSymbols || _writer.overridesWeakExternalSymbols )
+                       if ( _state.hasWeakExternalSymbols || _writer.overridesWeakExternalSymbols )
                                bits |= MH_WEAK_DEFINES;
                                bits |= MH_WEAK_DEFINES;
-                       if ( _writer.usesWeakExternalSymbols || _writer.hasWeakExternalSymbols )
+                       if ( _writer.usesWeakExternalSymbols || _state.hasWeakExternalSymbols )
                                bits |= MH_BINDS_TO_WEAK;
                        if ( _options.prebind() )
                                bits |= MH_PREBOUND;
                                bits |= MH_BINDS_TO_WEAK;
                        if ( _options.prebind() )
                                bits |= MH_PREBOUND;
@@ -578,10 +655,12 @@ uint32_t HeaderAndLoadCommandsAtom<A>::flags() const
                                bits |= MH_PIE;
                        if ( _options.markAutoDeadStripDylib() ) 
                                bits |= MH_DEAD_STRIPPABLE_DYLIB;
                                bits |= MH_PIE;
                        if ( _options.markAutoDeadStripDylib() ) 
                                bits |= MH_DEAD_STRIPPABLE_DYLIB;
-                       if ( _writer.hasThreadLocalVariableDefinitions )
+                       if ( _state.hasThreadLocalVariableDefinitions )
                                bits |= MH_HAS_TLV_DESCRIPTORS;
                        if ( _options.hasNonExecutableHeap() )
                                bits |= MH_NO_HEAP_EXECUTION;
                                bits |= MH_HAS_TLV_DESCRIPTORS;
                        if ( _options.hasNonExecutableHeap() )
                                bits |= MH_NO_HEAP_EXECUTION;
+                       if ( _options.markAppExtensionSafe() && (_options.outputKind() == Options::kDynamicLibrary) )
+                               bits |= MH_APP_EXTENSION_SAFE;
                }
                if ( _options.hasExecutableStack() )
                        bits |= MH_ALLOW_STACK_EXECUTION;
                }
                if ( _options.hasExecutableStack() )
                        bits |= MH_ALLOW_STACK_EXECUTION;
@@ -600,7 +679,6 @@ template <> uint32_t HeaderAndLoadCommandsAtom<arm>::cpuType() const        { return CP
 template <> uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuType() const { return CPU_TYPE_ARM64; }
 
 
 template <> uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuType() const { return CPU_TYPE_ARM64; }
 
 
-
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86>::cpuSubType() const
 {
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86>::cpuSubType() const
 {
@@ -610,10 +688,10 @@ uint32_t HeaderAndLoadCommandsAtom<x86>::cpuSubType() const
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86_64>::cpuSubType() const
 {
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86_64>::cpuSubType() const
 {
-       if ( (_options.outputKind() == Options::kDynamicExecutable) && (_options.macosxVersionMin() >= ld::mac10_5) )
-               return (CPU_SUBTYPE_X86_64_ALL | 0x80000000);
+       if ( (_options.outputKind() == Options::kDynamicExecutable) && (_state.cpuSubType == CPU_SUBTYPE_X86_64_ALL) && (_options.macosxVersionMin() >= ld::mac10_5) )
+               return (_state.cpuSubType | 0x80000000);
        else
        else
-               return CPU_SUBTYPE_X86_64_ALL;
+               return _state.cpuSubType;
 }
 
 template <>
 }
 
 template <>
@@ -625,7 +703,7 @@ uint32_t HeaderAndLoadCommandsAtom<arm>::cpuSubType() const
 template <>
 uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuSubType() const
 {
 template <>
 uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuSubType() const
 {
-       return CPU_SUBTYPE_ARM64_ALL;
+       return _state.cpuSubType;
 }
 
 
 }
 
 
@@ -669,7 +747,7 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copySingleSegmentLoadCommand(uint8_t* p)
                if ( cmd->fileoff() == 0 )
                        cmd->set_fileoff(fsect->fileOffset);
                cmd->set_vmsize(fsect->address + fsect->size - cmd->vmaddr());
                if ( cmd->fileoff() == 0 )
                        cmd->set_fileoff(fsect->fileOffset);
                cmd->set_vmsize(fsect->address + fsect->size - cmd->vmaddr());
-               if ( (fsect->type() != ld::Section::typeZeroFill) && (fsect->type() != ld::Section::typeTentativeDefs) )
+               if ( !sectionTakesNoDiskSpace(fsect) )
                        cmd->set_filesize(fsect->fileOffset + fsect->size - cmd->fileoff());
                ++msect;
        }
                        cmd->set_filesize(fsect->fileOffset + fsect->size - cmd->fileoff());
                ++msect;
        }
@@ -681,6 +759,7 @@ struct SegInfo {
                                                                                                SegInfo(const char* n, const Options&);
        const char*                                                                     segName;
        uint32_t                                                                        nonHiddenSectionCount;
                                                                                                SegInfo(const char* n, const Options&);
        const char*                                                                     segName;
        uint32_t                                                                        nonHiddenSectionCount;
+       uint32_t                                                                        nonSectCreateSections;
        uint32_t                                                                        maxProt;
        uint32_t                                                                        initProt;
        std::vector<ld::Internal::FinalSection*>        sections;
        uint32_t                                                                        maxProt;
        uint32_t                                                                        initProt;
        std::vector<ld::Internal::FinalSection*>        sections;
@@ -688,7 +767,7 @@ struct SegInfo {
 
 
 SegInfo::SegInfo(const char* n, const Options& opts) 
 
 
 SegInfo::SegInfo(const char* n, const Options& opts) 
-       : segName(n), nonHiddenSectionCount(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n)) 
+       : segName(n), nonHiddenSectionCount(0), nonSectCreateSections(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n))
 { 
 }
 
 { 
 }
 
@@ -711,6 +790,8 @@ uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection*
                                return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
                        else if ( (strncmp(sect->sectionName(), "__objc_nlcatlist", 16) == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
                                return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
                                return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
                        else if ( (strncmp(sect->sectionName(), "__objc_nlcatlist", 16) == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
                                return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
+                       else if (  (_options.outputKind() == Options::kObjectFile) && !sect->atoms.empty() && sect->atoms.front()->dontDeadStripIfReferencesLive() )
+                               return S_REGULAR | S_ATTR_LIVE_SUPPORT;
                        else
                                return S_REGULAR;
                case ld::Section::typeCode:
                        else
                                return S_REGULAR;
                case ld::Section::typeCode:
@@ -741,6 +822,9 @@ uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection*
                case ld::Section::typeTempLTO:
                        assert(0 && "typeTempLTO should not make it to final linked image");
                        return S_REGULAR;
                case ld::Section::typeTempLTO:
                        assert(0 && "typeTempLTO should not make it to final linked image");
                        return S_REGULAR;
+               case ld::Section::typeTempAlias:
+                       assert(0 && "typeAlias should not make it to final linked image");
+                       return S_REGULAR;
                case ld::Section::typeAbsoluteSymbols:
                        assert(0 && "typeAbsoluteSymbols should not make it to final linked image");
                        return S_REGULAR;
                case ld::Section::typeAbsoluteSymbols:
                        assert(0 && "typeAbsoluteSymbols should not make it to final linked image");
                        return S_REGULAR;
@@ -827,6 +911,8 @@ uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection*
                        return S_REGULAR;
                case ld::Section::typeDebug:
                        return S_REGULAR | S_ATTR_DEBUG;
                        return S_REGULAR;
                case ld::Section::typeDebug:
                        return S_REGULAR | S_ATTR_DEBUG;
+               case ld::Section::typeSectCreate:
+                       return S_REGULAR;
        }
        return S_REGULAR;
 }
        }
        return S_REGULAR;
 }
@@ -851,7 +937,7 @@ bool HeaderAndLoadCommandsAtom<A>::sectionTakesNoDiskSpace(ld::Internal::FinalSe
 
 
 template <typename A>
 
 
 template <typename A>
-uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p) const
+uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p, uint8_t* base) const
 {
        // group sections into segments
        std::vector<SegInfo> segs;
 {
        // group sections into segments
        std::vector<SegInfo> segs;
@@ -871,6 +957,9 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p) const
                }
                if ( ! sect->isSectionHidden() ) 
                        segs.back().nonHiddenSectionCount++;
                }
                if ( ! sect->isSectionHidden() ) 
                        segs.back().nonHiddenSectionCount++;
+               if ( sect->type() != ld::Section::typeSectCreate )
+                       segs.back().nonSectCreateSections++;
+
                segs.back().sections.push_back(sect);
        }
        // write out segment load commands for each section with trailing sections
                segs.back().sections.push_back(sect);
        }
        // write out segment load commands for each section with trailing sections
@@ -907,7 +996,9 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p) const
                segCmd->set_maxprot(si.maxProt);
                segCmd->set_initprot(si.initProt);
                segCmd->set_nsects(si.nonHiddenSectionCount);
                segCmd->set_maxprot(si.maxProt);
                segCmd->set_initprot(si.initProt);
                segCmd->set_nsects(si.nonHiddenSectionCount);
-               segCmd->set_flags(0);
+               segCmd->set_flags(si.nonSectCreateSections ? 0 : SG_NORELOC); // FIXME, really should check all References
+               if ( strcmp(segCmd->segname(), "__LINKEDIT") == 0 )
+                       _linkeditCmdOffset = p - base;
                p += sizeof(macho_segment_command<P>);
                macho_section<P>* msect = (macho_section<P>*)p;
                for (std::vector<ld::Internal::FinalSection*>::iterator sit = si.sections.begin(); sit != si.sections.end(); ++sit) {
                p += sizeof(macho_segment_command<P>);
                macho_section<P>* msect = (macho_section<P>*)p;
                for (std::vector<ld::Internal::FinalSection*>::iterator sit = si.sections.begin(); sit != si.sections.end(); ++sit) {
@@ -935,8 +1026,9 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p) const
 
 
 template <typename A>
 
 
 template <typename A>
-uint8_t* HeaderAndLoadCommandsAtom<A>::copySymbolTableLoadCommand(uint8_t* p) const
+uint8_t* HeaderAndLoadCommandsAtom<A>::copySymbolTableLoadCommand(uint8_t* p, uint8_t* base) const
 {
 {
+       _symboltableCmdOffset = p - base;
        // build LC_SYMTAB command
        macho_symtab_command<P>*   symbolTableCmd = (macho_symtab_command<P>*)p;
        symbolTableCmd->set_cmd(LC_SYMTAB);
        // build LC_SYMTAB command
        macho_symtab_command<P>*   symbolTableCmd = (macho_symtab_command<P>*)p;
        symbolTableCmd->set_cmd(LC_SYMTAB);
@@ -1090,24 +1182,67 @@ template <typename A>
 uint8_t* HeaderAndLoadCommandsAtom<A>::copyVersionLoadCommand(uint8_t* p) const
 {
        macho_version_min_command<P>* cmd = (macho_version_min_command<P>*)p;
 uint8_t* HeaderAndLoadCommandsAtom<A>::copyVersionLoadCommand(uint8_t* p) const
 {
        macho_version_min_command<P>* cmd = (macho_version_min_command<P>*)p;
-       ld::MacVersionMin macVersion = _options.macosxVersionMin();
-       ld::IOSVersionMin iOSVersion = _options.iOSVersionMin();
-       assert( (macVersion != ld::macVersionUnset) || (iOSVersion != ld::iOSVersionUnset) );
-       if ( macVersion != ld::macVersionUnset ) {
-               cmd->set_cmd(LC_VERSION_MIN_MACOSX);
-               cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
-               cmd->set_version((uint32_t)macVersion);
-               cmd->set_sdk(_options.sdkVersion());
-       }
-       else {
-               cmd->set_cmd(LC_VERSION_MIN_IPHONEOS);
-               cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
-               cmd->set_version((uint32_t)iOSVersion);
-               cmd->set_sdk(_options.sdkVersion());
+       switch (_platform) {
+               case Options::kPlatformOSX:
+                       cmd->set_cmd(LC_VERSION_MIN_MACOSX);
+                       cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+                       cmd->set_version(_state.minOSVersion);
+                       cmd->set_sdk(_options.sdkVersion());
+                       break;
+               case Options::kPlatformiOS:
+                       cmd->set_cmd(LC_VERSION_MIN_IPHONEOS);
+                       cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+                       cmd->set_version(_state.minOSVersion);
+                       cmd->set_sdk(_options.sdkVersion());
+                       break;
+               case Options::kPlatformWatchOS:
+                       cmd->set_cmd(LC_VERSION_MIN_WATCHOS);
+                       cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+                       cmd->set_version(_state.minOSVersion);
+                       cmd->set_sdk(_options.sdkVersion());
+                       break;
+#if SUPPORT_APPLE_TV
+               case Options::kPlatform_tvOS:
+                       cmd->set_cmd(LC_VERSION_MIN_TVOS);
+                       cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+                       cmd->set_version(_state.minOSVersion);
+                       cmd->set_sdk(_options.sdkVersion());
+                       break;
+#endif
+               case Options::kPlatformUnknown:
+                       assert(0 && "unknown platform");
+                       break;
+               case Options::kPlatform_bridgeOS:
+                       assert(0 && "bridgeOS uses LC_BUILD_VERSION");
+                       break;
        }
        return p + sizeof(macho_version_min_command<P>);
 }
 
        }
        return p + sizeof(macho_version_min_command<P>);
 }
 
+
+
+template <typename A>
+uint8_t* HeaderAndLoadCommandsAtom<A>::copyBuildVersionLoadCommand(uint8_t* p) const
+{
+       macho_build_version_command<P>* cmd = (macho_build_version_command<P>*)p;
+       
+       cmd->set_cmd(LC_BUILD_VERSION);
+       cmd->set_cmdsize(alignedSize(sizeof(macho_build_version_command<P>) + sizeof(macho_build_tool_version<P>)*_toolsVersions.size()));
+       cmd->set_platform(_options.platform());
+       cmd->set_minos(_state.minOSVersion);
+       cmd->set_sdk(_options.sdkVersion());
+       cmd->set_ntools(_toolsVersions.size());
+       macho_build_tool_version<P>* tools = (macho_build_tool_version<P>*)(p + sizeof(macho_build_version_command<P>));
+       for (uint64_t tool : _toolsVersions) {
+               tools->set_tool((uint64_t)tool >> 32);
+               tools->set_version(tool & 0xFFFFFFFF);
+               ++tools;
+       }
+
+       return p + cmd->cmdsize();
+}
+
+
 template <typename A>
 uint8_t* HeaderAndLoadCommandsAtom<A>::copySourceVersionLoadCommand(uint8_t* p) const
 {
 template <typename A>
 uint8_t* HeaderAndLoadCommandsAtom<A>::copySourceVersionLoadCommand(uint8_t* p) const
 {
@@ -1144,7 +1279,7 @@ uint8_t* HeaderAndLoadCommandsAtom<x86>::copyThreadsLoadCommand(uint8_t* p) cons
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86_64>::threadLoadCommandSize() const
 {
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86_64>::threadLoadCommandSize() const
 {
-       return this->alignedSize(16 + x86_THREAD_STATE64_COUNT * 4); 
+       return this->alignedSize(16 + 42*4);    // base size + x86_THREAD_STATE64_COUNT * 4
 }
 
 template <>
 }
 
 template <>
@@ -1155,8 +1290,8 @@ uint8_t* HeaderAndLoadCommandsAtom<x86_64>::copyThreadsLoadCommand(uint8_t* p) c
        macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
        cmd->set_cmd(LC_UNIXTHREAD);
        cmd->set_cmdsize(threadLoadCommandSize());
        macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
        cmd->set_cmd(LC_UNIXTHREAD);
        cmd->set_cmdsize(threadLoadCommandSize());
-       cmd->set_flavor(x86_THREAD_STATE64);                    
-       cmd->set_count(x86_THREAD_STATE64_COUNT);       
+       cmd->set_flavor(4);                             // x86_THREAD_STATE64
+       cmd->set_count(42);                             // x86_THREAD_STATE64_COUNT
        cmd->set_thread_register(16, start);            // rip 
        if ( _options.hasCustomStack() )
                cmd->set_thread_register(7, _options.customStackAddr());        // r1
        cmd->set_thread_register(16, start);            // rip 
        if ( _options.hasCustomStack() )
                cmd->set_thread_register(7, _options.customStackAddr());        // r1
@@ -1259,14 +1394,21 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copyDylibLoadCommand(uint8_t* p, const ld
 {
        uint32_t sz = alignedSize(sizeof(macho_dylib_command<P>) + strlen(dylib->installPath()) + 1);
        macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)p;
 {
        uint32_t sz = alignedSize(sizeof(macho_dylib_command<P>) + strlen(dylib->installPath()) + 1);
        macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)p;
+       bool weakLink = dylib->forcedWeakLinked() || dylib->allSymbolsAreWeakImported();
+       bool upward = dylib->willBeUpwardDylib() && _options.useUpwardDylibs();
+       bool reExport = dylib->willBeReExported() && _options.useSimplifiedDylibReExports();
+       if ( weakLink && upward )
+               warning("cannot weak upward link.  Dropping weak for %s", dylib->installPath());
+       if ( weakLink && reExport )
+               warning("cannot weak re-export a dylib.  Dropping weak for %s", dylib->installPath());
        if ( dylib->willBeLazyLoadedDylib() )
                cmd->set_cmd(LC_LAZY_LOAD_DYLIB);
        if ( dylib->willBeLazyLoadedDylib() )
                cmd->set_cmd(LC_LAZY_LOAD_DYLIB);
-       else if ( dylib->forcedWeakLinked() || dylib->allSymbolsAreWeakImported() )
-               cmd->set_cmd(LC_LOAD_WEAK_DYLIB);
-       else if ( dylib->willBeReExported() && _options.useSimplifiedDylibReExports() )
+       else if ( reExport )
                cmd->set_cmd(LC_REEXPORT_DYLIB);
                cmd->set_cmd(LC_REEXPORT_DYLIB);
-       else if ( dylib->willBeUpwardDylib() && _options.useUpwardDylibs() )
+       else if ( upward )
                cmd->set_cmd(LC_LOAD_UPWARD_DYLIB);
                cmd->set_cmd(LC_LOAD_UPWARD_DYLIB);
+       else if ( weakLink )
+               cmd->set_cmd(LC_LOAD_WEAK_DYLIB);
        else
                cmd->set_cmd(LC_LOAD_DYLIB);
        cmd->set_cmdsize(sz);
        else
                cmd->set_cmd(LC_LOAD_DYLIB);
        cmd->set_cmdsize(sz);
@@ -1397,14 +1539,15 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copyLinkerOptionsLoadCommand(uint8_t* p,
 }
 
 
 }
 
 
+
 template <typename A>
 template <typename A>
-uint8_t* HeaderAndLoadCommandsAtom<A>::copyDependentDRLoadCommand(uint8_t* p) const
+uint8_t* HeaderAndLoadCommandsAtom<A>::copyOptimizationHintsLoadCommand(uint8_t* p) const
 {
        macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
 {
        macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
-       cmd->set_cmd(LC_DYLIB_CODE_SIGN_DRS);
+       cmd->set_cmd(LC_LINKER_OPTIMIZATION_HINTS);
        cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
        cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
-       cmd->set_dataoff(_writer.dependentDRsSection->fileOffset);
-       cmd->set_datasize(_writer.dependentDRsSection->size);
+       cmd->set_dataoff(_writer.optimizationHintsSection->fileOffset);
+       cmd->set_datasize(_writer.optimizationHintsSection->size);
        return p + sizeof(macho_linkedit_data_command<P>);
 }
 
        return p + sizeof(macho_linkedit_data_command<P>);
 }
 
@@ -1430,7 +1573,7 @@ void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
        if ( _options.outputKind() == Options::kObjectFile )
                p = this->copySingleSegmentLoadCommand(p);
        else
        if ( _options.outputKind() == Options::kObjectFile )
                p = this->copySingleSegmentLoadCommand(p);
        else
-               p = this->copySegmentLoadCommands(p);
+               p = this->copySegmentLoadCommands(p, buffer);
        
        if ( _hasDylibIDLoadCommand )
                p = this->copyDylibIDLoadCommand(p);
        
        if ( _hasDylibIDLoadCommand )
                p = this->copyDylibIDLoadCommand(p);
@@ -1439,7 +1582,7 @@ void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
                p = this->copyDyldInfoLoadCommand(p);
                
        if ( _hasSymbolTableLoadCommand )
                p = this->copyDyldInfoLoadCommand(p);
                
        if ( _hasSymbolTableLoadCommand )
-               p = this->copySymbolTableLoadCommand(p);
+               p = this->copySymbolTableLoadCommand(p, buffer);
 
        if ( _hasDynamicSymbolTableLoadCommand )
                p = this->copyDynamicSymbolTableLoadCommand(p);
 
        if ( _hasDynamicSymbolTableLoadCommand )
                p = this->copyDynamicSymbolTableLoadCommand(p);
@@ -1456,6 +1599,9 @@ void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
        if ( _hasVersionLoadCommand )
                p = this->copyVersionLoadCommand(p);
 
        if ( _hasVersionLoadCommand )
                p = this->copyVersionLoadCommand(p);
 
+       if ( _hasBuildVersionLoadCommand )
+               p = this->copyBuildVersionLoadCommand(p);
+
        if ( _hasSourceVersionLoadCommand )
                p = this->copySourceVersionLoadCommand(p);
 
        if ( _hasSourceVersionLoadCommand )
                p = this->copySourceVersionLoadCommand(p);
 
@@ -1519,8 +1665,8 @@ void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
                }
        }
        
                }
        }
        
-       if ( _hasDependentDRInfo ) 
-               p = this->copyDependentDRLoadCommand(p);
+       if ( _hasOptimizationHints )
+               p = this->copyOptimizationHintsLoadCommand(p);
  
 }
 
  
 }