]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/HeaderAndLoadCommands.hpp
ld64-236.3.tar.gz
[apple/ld64.git] / src / ld / HeaderAndLoadCommands.hpp
index 395fc99e95054958857413a2f8e0e5821e3f0fd2..acbdf4f3057e8ada8386b1fd9c37475af705b4b7 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
  *
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -60,8 +60,6 @@ public:
 
        // overrides of ld::Atom
        virtual ld::File*                                                       file() const            { return NULL; }
-       virtual bool                                                            translationUnitSource(const char** dir, const char** nm) const
-                                                                                                                                       { return false; }
        virtual const char*                                                     name() const            { return "mach-o header and load commands"; }
        virtual uint64_t                                                        size() const;
        virtual uint64_t                                                        objectAddress() const { return _address; }
@@ -96,7 +94,9 @@ private:
        uint8_t*                                        copyRoutinesLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyUUIDLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyVersionLoadCommand(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*                                        copyEncryptionLoadCommand(uint8_t* p) const;
        uint8_t*                                        copySplitSegInfoLoadCommand(uint8_t* p) const;
        uint8_t*                                        copyDylibLoadCommand(uint8_t* p, const ld::dylib::File*) const;
@@ -106,8 +106,12 @@ private:
        uint8_t*                                        copySubLibraryLoadCommand(uint8_t* p, const char* name) 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*                                        copyOptimizationHintsLoadCommand(uint8_t* p) const;
+
        uint32_t                                        sectionFlags(ld::Internal::FinalSection* sect) const;
        bool                                            sectionTakesNoDiskSpace(ld::Internal::FinalSection* sect) const;
        
@@ -120,6 +124,7 @@ private:
        bool                                            _hasDyldLoadCommand;
        bool                                            _hasDylibIDLoadCommand;
        bool                                            _hasThreadLoadCommand;
+       bool                                            _hasEntryPointLoadCommand;
        bool                                            _hasEncryptionLoadCommand;
        bool                                            _hasSplitSegInfoLoadCommand;
        bool                                            _hasRoutinesLoadCommand;
@@ -130,6 +135,10 @@ private:
        bool                                            _hasSubFrameworkLoadCommand;
        bool                                            _hasVersionLoadCommand;
        bool                                            _hasFunctionStartsLoadCommand;
+       bool                                            _hasDataInCodeLoadCommand;
+       bool                                            _hasSourceVersionLoadCommand;
+       bool                                            _hasDependentDRInfo;
+       bool                                            _hasOptimizationHints;
        uint32_t                                        _dylibLoadCommmandsCount;
        uint32_t                                        _allowableClientLoadCommmandsCount;
        uint32_t                                        _dyldEnvironExrasCount;
@@ -137,6 +146,7 @@ private:
        std::vector<const char*>        _subUmbrellaNames;
        uint8_t                                         _uuid[16];
        mutable macho_uuid_command<P>*  _uuidCmdInOutputBuffer;
+       std::vector< std::vector<const char*> >  _linkerOptions;
        
        static ld::Section                      _s_section;
        static ld::Section                      _s_preload_section;
@@ -161,14 +171,14 @@ HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld:
        _hasDyldInfoLoadCommand = opts.makeCompressedDyldInfo();
        _hasDyldLoadCommand = ((opts.outputKind() == Options::kDynamicExecutable) || (_options.outputKind() == Options::kDyld));
        _hasDylibIDLoadCommand = (opts.outputKind() == Options::kDynamicLibrary);
-       _hasThreadLoadCommand = _hasDyldLoadCommand || (opts.outputKind() == Options::kStaticExecutable)
-                                                                                               || (opts.outputKind() == Options::kPreload)
-                                                                                               || (opts.outputKind() == Options::kDyld);
+       _hasThreadLoadCommand = _options.needsThreadLoadCommand();
+       _hasEntryPointLoadCommand = _options.needsEntryPointLoadCommand();
        _hasEncryptionLoadCommand = opts.makeEncryptable();
        _hasSplitSegInfoLoadCommand = opts.sharedRegionEligible();
        _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:
@@ -187,9 +197,25 @@ HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld:
                                        break;
                                }
                        }
+                       for (CStringSet::const_iterator it = _state.linkerOptionFrameworks.begin(); it != _state.linkerOptionFrameworks.end(); ++it) {
+                               const char* frameWorkName = *it;
+                               std::vector<const char*>* lo = new std::vector<const char*>();
+                               lo->push_back("-framework");
+                               lo->push_back(frameWorkName);
+                               _linkerOptions.push_back(*lo);
+                       };
+                       for (CStringSet::const_iterator it = _state.linkerOptionLibraries.begin(); it != _state.linkerOptionLibraries.end(); ++it) {
+                               const char* libName = *it;
+                               std::vector<const char*>* lo = new std::vector<const char*>();
+                               char * s = new char[strlen(libName)+3];
+                               strcpy(s, "-l");
+                               strcat(s, libName);
+                               lo->push_back(s);
+                               _linkerOptions.push_back(*lo);
+                       };
                        break;
                case Options::kStaticExecutable:
-                       _hasDynamicSymbolTableLoadCommand = false;
+                       _hasDynamicSymbolTableLoadCommand = opts.positionIndependentExecutable();
                        break;
                case Options::kPreload:
                        _hasDynamicSymbolTableLoadCommand = opts.positionIndependentExecutable();
@@ -199,9 +225,13 @@ HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld:
        _hasSubFrameworkLoadCommand = (_options.umbrellaName() != NULL);
        _hasVersionLoadCommand = _options.addVersionLoadCommand();
        _hasFunctionStartsLoadCommand = _options.addFunctionStarts();
+       _hasDataInCodeLoadCommand = _options.addDataInCodeInfo();
+       _hasSourceVersionLoadCommand = _options.needsSourceVersionLoadCommand();
+       _hasDependentDRInfo = _options.needsDependentDRInfo();
        _dylibLoadCommmandsCount = _writer.dylibCount();
        _allowableClientLoadCommmandsCount = _options.allowableClients().size();
        _dyldEnvironExrasCount = _options.dyldEnvironExtras().size();
+       
        if ( ! _options.useSimplifiedDylibReExports() ) {
                // target OS does not support LC_REEXPORT_DYLIB, so use old complicated load commands
                for(uint32_t ord=1; ord <= _writer.dylibCount(); ++ord) {
@@ -328,9 +358,15 @@ uint64_t HeaderAndLoadCommandsAtom<A>::size() const
 
        if ( _hasVersionLoadCommand )
                sz += sizeof(macho_version_min_command<P>);
+       
+       if ( _hasSourceVersionLoadCommand )
+               sz += sizeof(macho_source_version_command<P>);
                
        if ( _hasThreadLoadCommand )
                sz += this->threadLoadCommandSize();
+
+       if ( _hasEntryPointLoadCommand )
+               sz += sizeof(macho_entry_point_command<P>);
                
        if ( _hasEncryptionLoadCommand )
                sz += sizeof(macho_encryption_info_command<P>);
@@ -377,6 +413,26 @@ uint64_t HeaderAndLoadCommandsAtom<A>::size() const
        if ( _hasFunctionStartsLoadCommand )
                sz += sizeof(macho_linkedit_data_command<P>);
 
+       if ( _hasDataInCodeLoadCommand )
+               sz += sizeof(macho_linkedit_data_command<P>);
+
+       if ( !_linkerOptions.empty() ) {
+               for (ld::relocatable::File::LinkerOptionsList::const_iterator it = _linkerOptions.begin(); it != _linkerOptions.end(); ++it) {
+                       uint32_t s = sizeof(macho_linker_option_command<P>);
+                       const std::vector<const char*>& options = *it;
+                       for (std::vector<const char*>::const_iterator t=options.begin(); t != options.end(); ++t) {
+                               s += (strlen(*t) + 1);
+                       }
+                       sz += alignedSize(s);
+               }
+       }
+       
+       if ( _hasDependentDRInfo ) 
+               sz += sizeof(macho_linkedit_data_command<P>);
+       
+       if ( _hasOptimizationHints )
+               sz += sizeof(macho_linkedit_data_command<P>);
+               
        return sz;
 }
 
@@ -409,8 +465,14 @@ uint32_t HeaderAndLoadCommandsAtom<A>::commandsCount() const
        if ( _hasVersionLoadCommand )
                ++count;
 
+       if ( _hasSourceVersionLoadCommand )
+               ++count;
+               
        if ( _hasThreadLoadCommand )
                ++count;
+       
+       if ( _hasEntryPointLoadCommand )
+               ++count;
                
        if ( _hasEncryptionLoadCommand )
                ++count;
@@ -436,6 +498,21 @@ uint32_t HeaderAndLoadCommandsAtom<A>::commandsCount() const
        if ( _hasFunctionStartsLoadCommand )
                ++count;
 
+       if ( _hasDataInCodeLoadCommand )
+               ++count;
+
+       if ( !_linkerOptions.empty() ) {
+               for (ld::relocatable::File::LinkerOptionsList::const_iterator it = _linkerOptions.begin(); it != _linkerOptions.end(); ++it) {
+                       ++count;
+               }
+       }
+
+       if ( _hasDependentDRInfo ) 
+               ++count;
+       
+       if ( _hasOptimizationHints )
+               ++count;
+               
        return count;
 }
 
@@ -473,6 +550,8 @@ uint32_t HeaderAndLoadCommandsAtom<A>::flags() const
        else {
                if ( _options.outputKind() == Options::kStaticExecutable ) {
                        bits |= MH_NOUNDEFS;
+                       if ( _options.positionIndependentExecutable() ) 
+                               bits |= MH_PIE;
                }
                else if ( _options.outputKind() == Options::kPreload ) {
                        bits |= MH_NOUNDEFS;
@@ -491,9 +570,9 @@ uint32_t HeaderAndLoadCommandsAtom<A>::flags() const
                                        bits |= MH_FORCE_FLAT;
                                        break;
                        }
-                       if ( _writer.hasWeakExternalSymbols || _writer.overridesWeakExternalSymbols )
+                       if ( _state.hasWeakExternalSymbols || _writer.overridesWeakExternalSymbols )
                                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;
@@ -508,7 +587,7 @@ uint32_t HeaderAndLoadCommandsAtom<A>::flags() const
                                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;
@@ -519,33 +598,17 @@ uint32_t HeaderAndLoadCommandsAtom<A>::flags() const
        return bits;
 }
 
-template <> uint32_t HeaderAndLoadCommandsAtom<ppc>::magic() const             { return MH_MAGIC; }
-template <> uint32_t HeaderAndLoadCommandsAtom<ppc64>::magic() const           { return MH_MAGIC_64; }
 template <> uint32_t HeaderAndLoadCommandsAtom<x86>::magic() const             { return MH_MAGIC; }
 template <> uint32_t HeaderAndLoadCommandsAtom<x86_64>::magic() const  { return MH_MAGIC_64; }
 template <> uint32_t HeaderAndLoadCommandsAtom<arm>::magic() const             { return MH_MAGIC; }
+template <> uint32_t HeaderAndLoadCommandsAtom<arm64>::magic() const           { return MH_MAGIC_64; }
 
-template <> uint32_t HeaderAndLoadCommandsAtom<ppc>::cpuType() const   { return CPU_TYPE_POWERPC; }
-template <> uint32_t HeaderAndLoadCommandsAtom<ppc64>::cpuType() const { return CPU_TYPE_POWERPC64; }
 template <> uint32_t HeaderAndLoadCommandsAtom<x86>::cpuType() const   { return CPU_TYPE_I386; }
 template <> uint32_t HeaderAndLoadCommandsAtom<x86_64>::cpuType() const        { return CPU_TYPE_X86_64; }
 template <> uint32_t HeaderAndLoadCommandsAtom<arm>::cpuType() const   { return CPU_TYPE_ARM; }
+template <> uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuType() const { return CPU_TYPE_ARM64; }
 
 
-template <>
-uint32_t HeaderAndLoadCommandsAtom<ppc>::cpuSubType() const
-{
-       return _state.cpuSubType;
-}
-
-template <>
-uint32_t HeaderAndLoadCommandsAtom<ppc64>::cpuSubType() const
-{
-       if ( (_options.outputKind() == Options::kDynamicExecutable) && (_options.macosxVersionMin() >= ld::mac10_5) )
-               return (CPU_SUBTYPE_POWERPC_ALL | 0x80000000);
-       else
-               return CPU_SUBTYPE_POWERPC_ALL;
-}
 
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86>::cpuSubType() const
@@ -556,10 +619,10 @@ uint32_t HeaderAndLoadCommandsAtom<x86>::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
-               return CPU_SUBTYPE_X86_64_ALL;
+               return _state.cpuSubType;
 }
 
 template <>
@@ -568,6 +631,12 @@ uint32_t HeaderAndLoadCommandsAtom<arm>::cpuSubType() const
        return _state.cpuSubType;
 }
 
+template <>
+uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuSubType() const
+{
+       return CPU_SUBTYPE_ARM64_ALL;
+}
+
 
 
 template <typename A>
@@ -649,6 +718,8 @@ uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection*
                                return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
                        else if ( (strncmp(sect->sectionName(), "__objc_nlclslist", 16) == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
                                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
                                return S_REGULAR;
                case ld::Section::typeCode:
@@ -722,7 +793,12 @@ uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection*
                        else
                                return S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS;
                case ld::Section::typeNonLazyPointer:
-                       return S_NON_LAZY_SYMBOL_POINTERS;
+                       if ( _options.outputKind() == Options::kKextBundle  )
+                               return S_REGULAR;
+                       else if ( (_options.outputKind() == Options::kStaticExecutable) && _options.positionIndependentExecutable() )
+                               return S_REGULAR;
+                       else
+                               return S_NON_LAZY_SYMBOL_POINTERS;
                case ld::Section::typeDyldInfo:
                        return S_REGULAR;
                case ld::Section::typeLazyDylibPointer:
@@ -733,7 +809,13 @@ uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection*
                        else
                                return S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS;
                case ld::Section::typeInitializerPointers:
-                       return S_MOD_INIT_FUNC_POINTERS;
+                       // <rdar://problem/11456679> i386 kexts need different section type
+                       if ( (_options.outputKind() == Options::kObjectFile) 
+                                       && (strcmp(sect->sectionName(), "__constructor") == 0) 
+                                       && (strcmp(sect->segmentName(), "__TEXT") == 0) )
+                               return S_REGULAR;
+                       else
+                               return S_MOD_INIT_FUNC_POINTERS;
                case ld::Section::typeTerminatorPointers:
                        return S_MOD_TERM_FUNC_POINTERS;
                case ld::Section::typeTLVInitialValues:
@@ -973,7 +1055,7 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copyDylibIDLoadCommand(uint8_t* p) const
        cmd->set_cmdsize(sz);
        cmd->set_name_offset();
        cmd->set_timestamp(1);  // needs to be some constant value that is different than DylibLoadCommandsAtom uses
-       cmd->set_current_version(_options.currentVersion());
+       cmd->set_current_version(_options.currentVersion32());
        cmd->set_compatibility_version(_options.compatibilityVersion());
        strcpy((char*)&p[sizeof(macho_dylib_command<P>)], _options.installPath());
        return p + sz;
@@ -1024,62 +1106,27 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copyVersionLoadCommand(uint8_t* p) const
                cmd->set_cmd(LC_VERSION_MIN_MACOSX);
                cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
                cmd->set_version((uint32_t)macVersion);
-               cmd->set_reserved(0);
+               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_reserved(0);
+               cmd->set_sdk(_options.sdkVersion());
        }
        return p + sizeof(macho_version_min_command<P>);
 }
 
-
-template <>
-uint32_t HeaderAndLoadCommandsAtom<ppc>::threadLoadCommandSize() const
-{
-       return this->alignedSize(16 + 40*4);    // base size + PPC_THREAD_STATE_COUNT * 4
-}
-
-
-template <>
-uint8_t* HeaderAndLoadCommandsAtom<ppc>::copyThreadsLoadCommand(uint8_t* p) const
-{
-       assert(_state.entryPoint != NULL);
-       pint_t start = _state.entryPoint->finalAddress(); 
-       macho_thread_command<ppc::P>* cmd = (macho_thread_command<ppc::P>*)p;
-       cmd->set_cmd(LC_UNIXTHREAD);
-       cmd->set_cmdsize(threadLoadCommandSize());
-       cmd->set_flavor(1);                             // PPC_THREAD_STATE
-       cmd->set_count(40);                             // PPC_THREAD_STATE_COUNT;
-       cmd->set_thread_register(0, start);
-       if ( _options.hasCustomStack() )
-               cmd->set_thread_register(3, _options.customStackAddr());        // r1
-       return p + threadLoadCommandSize();
-}
-
-template <>
-uint32_t HeaderAndLoadCommandsAtom<ppc64>::threadLoadCommandSize() const
+template <typename A>
+uint8_t* HeaderAndLoadCommandsAtom<A>::copySourceVersionLoadCommand(uint8_t* p) const
 {
-       return this->alignedSize(16 + 76*4);    // base size + PPC_THREAD_STATE64_COUNT * 4
+       macho_source_version_command<P>* cmd = (macho_source_version_command<P>*)p;
+       cmd->set_cmd(LC_SOURCE_VERSION);
+       cmd->set_cmdsize(sizeof(macho_source_version_command<P>));
+       cmd->set_version(_options.sourceVersion());
+       return p + sizeof(macho_source_version_command<P>);
 }
 
-template <>
-uint8_t* HeaderAndLoadCommandsAtom<ppc64>::copyThreadsLoadCommand(uint8_t* p) const
-{
-       assert(_state.entryPoint != NULL);
-       pint_t start = _state.entryPoint->finalAddress(); 
-       macho_thread_command<ppc::P>* cmd = (macho_thread_command<ppc::P>*)p;
-       cmd->set_cmd(LC_UNIXTHREAD);
-       cmd->set_cmdsize(threadLoadCommandSize());
-       cmd->set_flavor(5);                             // PPC_THREAD_STATE64
-       cmd->set_count(76);                             // PPC_THREAD_STATE64_COUNT;
-       cmd->set_thread_register(0, start);
-       if ( _options.hasCustomStack() )
-               cmd->set_thread_register(3, _options.customStackAddr());        // r1
-       return p + threadLoadCommandSize();
-}
 
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86>::threadLoadCommandSize() const
@@ -1149,11 +1196,51 @@ uint8_t* HeaderAndLoadCommandsAtom<arm>::copyThreadsLoadCommand(uint8_t* p) cons
        return p + threadLoadCommandSize();
 }
 
+
+template <>
+uint32_t HeaderAndLoadCommandsAtom<arm64>::threadLoadCommandSize() const
+{
+       return this->alignedSize(16 + 34 * 8); // base size + ARM_EXCEPTION_STATE64_COUNT * 4
+}
+
+template <>
+uint8_t* HeaderAndLoadCommandsAtom<arm64>::copyThreadsLoadCommand(uint8_t* p) const
+{
+       assert(_state.entryPoint != NULL);
+       pint_t start = _state.entryPoint->finalAddress(); 
+       macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
+       cmd->set_cmd(LC_UNIXTHREAD);
+       cmd->set_cmdsize(threadLoadCommandSize());
+       cmd->set_flavor(6);      // ARM_THREAD_STATE64
+       cmd->set_count(68);      // ARM_EXCEPTION_STATE64_COUNT
+       cmd->set_thread_register(32, start);            // pc 
+       if ( _options.hasCustomStack() )
+               cmd->set_thread_register(31, _options.customStackAddr());       // sp 
+       return p + threadLoadCommandSize();
+}
+
+
+template <typename A>
+uint8_t* HeaderAndLoadCommandsAtom<A>::copyEntryPointLoadCommand(uint8_t* p) const
+{
+       macho_entry_point_command<P>* cmd = (macho_entry_point_command<P>*)p;
+       cmd->set_cmd(LC_MAIN);
+       cmd->set_cmdsize(sizeof(macho_entry_point_command<P>));
+       assert(_state.entryPoint != NULL);
+       pint_t start = _state.entryPoint->finalAddress(); 
+       if ( _state.entryPoint->isThumb() )
+               start |= 1ULL;
+       cmd->set_entryoff(start - this->finalAddress());
+       cmd->set_stacksize(_options.hasCustomStack() ? _options.customStackSize() : 0 );
+       return p + sizeof(macho_entry_point_command<P>);
+}
+
+
 template <typename A>
 uint8_t* HeaderAndLoadCommandsAtom<A>::copyEncryptionLoadCommand(uint8_t* p) const
 {
        macho_encryption_info_command<P>* cmd = (macho_encryption_info_command<P>*)p;
-       cmd->set_cmd(LC_ENCRYPTION_INFO);
+       cmd->set_cmd(sizeof(typename A::P::uint_t) == 4 ? LC_ENCRYPTION_INFO : LC_ENCRYPTION_INFO_64);
        cmd->set_cmdsize(sizeof(macho_encryption_info_command<P>));
        assert(_writer.encryptedTextStartOffset() != 0);
        assert(_writer.encryptedTextEndOffset() != 0);
@@ -1286,6 +1373,64 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copyFunctionStartsLoadCommand(uint8_t* p)
 }
 
 
+template <typename A>
+uint8_t* HeaderAndLoadCommandsAtom<A>::copyDataInCodeLoadCommand(uint8_t* p) const
+{
+       macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
+       cmd->set_cmd(LC_DATA_IN_CODE);
+       cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
+       cmd->set_dataoff(_writer.dataInCodeSection->fileOffset);
+       cmd->set_datasize(_writer.dataInCodeSection->size);
+       return p + sizeof(macho_linkedit_data_command<P>);
+}
+
+
+template <typename A>
+uint8_t* HeaderAndLoadCommandsAtom<A>::copyLinkerOptionsLoadCommand(uint8_t* p, const std::vector<const char*>& options) const
+{
+       macho_linker_option_command<P>* cmd = (macho_linker_option_command<P>*)p;
+       cmd->set_cmd(LC_LINKER_OPTION);
+       cmd->set_count(options.size());
+       char* buffer = cmd->buffer();
+       uint32_t sz = sizeof(macho_linker_option_command<P>);
+       for (std::vector<const char*>::const_iterator it=options.begin(); it != options.end(); ++it) {
+               const char* opt = *it;
+               uint32_t len = strlen(opt);
+               strcpy(buffer, opt);
+               sz += (len + 1);
+               buffer += (len + 1);
+       }
+       sz = alignedSize(sz);
+       cmd->set_cmdsize(sz);   
+       return p + sz;
+}
+
+
+template <typename A>
+uint8_t* HeaderAndLoadCommandsAtom<A>::copyDependentDRLoadCommand(uint8_t* p) const
+{
+       macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
+       cmd->set_cmd(LC_DYLIB_CODE_SIGN_DRS);
+       cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
+       cmd->set_dataoff(_writer.dependentDRsSection->fileOffset);
+       cmd->set_datasize(_writer.dependentDRsSection->size);
+       return p + sizeof(macho_linkedit_data_command<P>);
+}
+
+
+
+template <typename A>
+uint8_t* HeaderAndLoadCommandsAtom<A>::copyOptimizationHintsLoadCommand(uint8_t* p) const
+{
+       macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
+       cmd->set_cmd(LC_LINKER_OPTIMIZATION_HINTS);
+       cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
+       cmd->set_dataoff(_writer.optimizationHintsSection->fileOffset);
+       cmd->set_datasize(_writer.optimizationHintsSection->size);
+       return p + sizeof(macho_linkedit_data_command<P>);
+}
+
+
 template <typename A>
 void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
@@ -1333,8 +1478,14 @@ void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
        if ( _hasVersionLoadCommand )
                p = this->copyVersionLoadCommand(p);
 
+       if ( _hasSourceVersionLoadCommand )
+               p = this->copySourceVersionLoadCommand(p);
+
        if ( _hasThreadLoadCommand )
                p = this->copyThreadsLoadCommand(p);
+       
+       if ( _hasEntryPointLoadCommand )
+               p = this->copyEntryPointLoadCommand(p);
                
        if ( _hasEncryptionLoadCommand )
                p = this->copyEncryptionLoadCommand(p);
@@ -1342,7 +1493,7 @@ void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
        if ( _hasSplitSegInfoLoadCommand )
                p = this->copySplitSegInfoLoadCommand(p);
                
-       for(uint32_t ord=1; ord <= _writer.dylibCount(); ++ord) {
+       for (uint32_t ord=1; ord <= _writer.dylibCount(); ++ord) {
                p = this->copyDylibLoadCommand(p, _writer.dylibByOrdinal(ord));
        }
 
@@ -1380,7 +1531,22 @@ void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
        if ( _hasFunctionStartsLoadCommand )
                p = this->copyFunctionStartsLoadCommand(p);
-               
+
+       if ( _hasDataInCodeLoadCommand )
+               p = this->copyDataInCodeLoadCommand(p);
+
+       if ( !_linkerOptions.empty() ) {
+               for (ld::relocatable::File::LinkerOptionsList::const_iterator it = _linkerOptions.begin(); it != _linkerOptions.end(); ++it) {
+                       p = this->copyLinkerOptionsLoadCommand(p, *it);
+               }
+       }
+       
+       if ( _hasDependentDRInfo ) 
+               p = this->copyDependentDRLoadCommand(p);
+       if ( _hasOptimizationHints )
+               p = this->copyOptimizationHintsLoadCommand(p);
 }