iOS 分析dyld工作过程 dyld-941.5源码

程序员 2024-9-12 16:22:28 97 0 来自 中国
dyld源码
苹果官方资源opensource
objc4-838可编译联调源码
一、相识相干概念

1.静态库、动态库

通常步伐都会依靠体系一些库, 库是什么呢? 着实库就是一些可实行的二进制文件, 能被操纵体系加载到内存内里中。库分为两种:静态库 / 动态库

  • 静态库:是一堆.o文件的聚集。格式.a, .lib等。链接阶段时静态库会被完备地复制, 一起打包在可实行文件中,被多次利用就有多份冗余拷贝。

    • 优点: 编译完成之后, 链接到目标步伐中, 同时打包到可实行文件内里, 不会有外部依靠。
    • 缺点: 静态库会有两份, 以是会导致目标步伐体积增大, 对内存, 性能, 速率斲丧很大。而且类似静态库每个app中都会拷贝一份。



  • 动态库:是一个已经完全链接后的镜像。格式.framework等。步伐编译时并不会链接到目标步伐中,目标步伐只会存储指向动态库的引用,在步伐运行时才被载入。苹果大部门都是动态库。

    • 优点: 不必要拷贝到目标步伐, 镌汰App包的体积;多个App可以利用同一个动态库, 共享内存, 节省资源;由于运行时才会去加载, 那么可以在App不利用时随时对库举行更换或更新, 更新机动。
    • 缺点: 动态载入会带来一部门性能丧失, 同时动态库也会使得步伐依靠于外部情况。一旦动态库没有或消散, 步伐会出现标题。

2.png 1.Xcode编译command + B产生可实行文件的过程:



  • a.预编译
    处置惩罚源代码文件中以#开头的预编译的下令(#import/#include等等);把包罗的文件插入到指定的位置;更换代码中的宏界说;删除代码里的表明等等。产生.i文件。
  • b.编译
    词法分析;语法分析;语义分析;生成相应的汇编代码文件。 产生.s文件(汇编文件)
  • c.汇编
    将汇编代码文件翻译成呆板指令,呆板指令会生成.o文件。
  • d.链接
    把之前全部操纵的文件链接到步伐内里来, 对.o文件中引用其他库的地方举行引用, 生成末了的 可实行文件。动态库与静态库区别着实就是链接的区别。

    • 静态链接:  链接器对.o文件举行符号网络、剖析和重定位;把全部的.o粘合在一起从而形成可实行文件。(在静态链接之后就不会再有静态库了)
    • 动态链接: dyld动态链接(下面有介绍)

2.点击App启动的过程:


  • a.体系调用 exec() 分配内存、开辟历程
  • b.app对应的可实行文件加载到内存
  • c.dyld动态链接器加载到内存:load dyld
  • d.dyld动态链接器进办法态链接:rebase->bing->Objc->initalizers
  • e.调起main()函数
启动时间的划分可以把main()函数作为关键点分割成两块
4.png
t1阶段,main()之前的处置惩罚所需时间,称为pre-main
5.png
t2阶段,main()及main()之后处置惩罚所需时间
t2阶段耗时的重要是业务代码
3.Mach-O是什么?

Mach-O: Mach Object文件格式的缩写,它是一种用于可实行文件,目标文件.o,动态库,内核转储的文件格式。作为a.out格式的替换,Mach-O提供了更强的扩展性,并提拔了符号表中信息的访问速率。
三种Mach-O格式的文件:可实行文件、dylib动态库、Bundle资源文件包
Mach-O由四部门构成:Mach-O头部、Load Command、section、Other Data,可以通过MachOView可检察可实行文件信息。
二、什么是dyld

本文重要介绍dyld源码实行流程。
在app启动加载过程中类和分类加载都不可制止的触及dyld,以是相识dyld源码可以让我们更好的明白app的工作原理。
什么是dyld?
dyld(the dynamic link editor 动态链接器):是苹果操纵体系的一个紧张的构成部门。在iOS/Mac OSX体系中,仅有很少量的历程只必要内核就能完成加载,根本上全部的历程都是动态链接的,以是Mach-O镜像文件中会有许多对外部的库和符号的引用,但是这些引用并不能直接用,在启动时还必须要通过这些引用举行内容的弥补,这个弥补工作就是由动态链接器dyld来完成的,也就是符号绑定。
在app被编译打包成可实行文件格式的Mach-O文件后,在步伐启动时交由dyld负责链接加载步伐。
dyld是开源的,可以通过苹果官网下载它的dyld源码,本文的对应的版本是941.5。dyld4是iOS15发布的。

  • dyld3: 相比dyld2新增预构建/闭包, 目标是将一些启动数据创建为闭包存到当地,下次启动将不再重新剖析数据,而是直接读取闭包内容
  • dyld4: 采取pre-build + just-in-time 预构建/闭包+及时剖析的双剖析模式, 将根据缓存有用与否选择符合的模式举行剖析, 同时也处置惩罚了闭包失效时候必要重修闭包的性能标题。
三、dyld工作流程

6.png 新建一个工程,在ViewController.m里重写+(void)load方法,在load方法上打个断点调试,运行app后在断点处输出其函数调用的堆栈:
8.png 新版本dyld: start开始接下来走 dyld4中prepare方法, 源码入口必要在start中开始探索。
(旧版本dyld: _dyld_start开始, 接下来走dyldbootstrap, 源码入口必要在dyld_start开始。)
1.start函数是dyld的开始

// dyld的入口点。内核加载dyld并跳转到__dyld_start,它设置一些寄存器并调用这个函数。// 注意:这个函数永久不会返回,它调用exit()。因此,堆栈掩护步伐是无用的,由于永久不会实行epilog。标志函数no-return禁用堆栈掩护。堆栈掩护器也会导致armv7k代码生成的标题,由于它通过prolog中的GOT槽访问随机值,但dyld还没有rebased。void start(const KernelArgs* kernArgs) __attribute__((noreturn)) __asm("start");void start(const KernelArgs* kernArgs){    // 发出kdebug跟踪点来指示dyld引导步伐已经启动 <rdar://46878536>    // 注意:这是在dyld rebased之前调用的,以是kdebug_trace_dyld_marker()不能利用任何全局变量    dyld3::kdebug_trace_dyld_marker(DBG_DYLD_TIMING_BOOTSTRAP_START, 0, 0, 0, 0);    // 走全部的fixups chains 和 rebase dyld    // 注意:withChainStarts()和fixupAllChainedFixups()不能利用任何静态数据指针,由于它们还没有rebased    const MachOAnalyzer* dyldMA = getDyldMH(); // 获取Mach-O分析器    assert(dyldMA->hasChainedFixups());    uintptr_t           slide = (long)dyldMA; // 全部基于修复链的图像的基址为0,因此slide == load address    __block Diagnostics diag;    dyldMA->withChainStarts(diag, 0, ^(const dyld_chained_starts_in_image* starts) {        dyldMA->fixupAllChainedFixups(diag, starts, slide, dyld3::Array<const void*>(), nullptr);    });    diag.assertNoError();    // 现在,我们可以调用利用DATA的函数    mach_init(); // mach消息初始化    // 为stack canary设置随机值    __guard_setup(kernArgs->findApple()); // 栈溢出掩护    // 设置以便open_with_subsystem()工作    _subsystem_init(kernArgs->findApple());    // 在__DATA_CONST中将ProcessConfig对象变为只读之前,利用placement new来构造它    ProcessConfig& config = *new ((ProcessConfig*)sConfigBuffer) ProcessConfig(kernArgs, sSyscallDelegate);    // 使__DATA_CONST只读(内核映射为r/w)    dyldMA->forEachSegment(^(const MachOAnalyzer::SegmentInfo& segInfo, bool& stop) {        if ( segInfo.readOnlyData ) {            const uint8_t* start = (uint8_t*)(segInfo.vmAddr + slide);            size_t         size  = (size_t)segInfo.vmSize;            sSyscallDelegate.mprotect((void*)start, size, PROT_READ);        }    });#if !SUPPPORT_PRE_LC_MAIN    // 堆栈分配RuntimeLocks。它们不能位于通常是只读的Allocator池中    RuntimeLocks  sLocks;#endif    // 创建Allocator和APIs/RuntimeState对象    APIs& state = APIs::bootstrap(config, sLocks);    // 加载步伐的全部依靠项并将它们绑定在一起    MainFunc appMain = prepare(state, dyldMA);    // 现在使全部的dyld分配的数据结构只读    state.decWritable();    // 调用main(),假如它返回,调用exit()并返回结果    // 注意:这是颠末构造的,以便在步伐的主线程中回溯时只在“main”下面体现“start”。    int result = appMain(state.config.process.argc, state.config.process.argv, state.config.process.envp, state.config.process.apple);    // 假如我们到达这里,main()返回(而不是步伐调用exit())#if TARGET_OS_OSX    // <rdar://74518676> libSystemHelpers不是为模仿器设置的,因此直接调用_exit()    if ( MachOFile::isSimulatorPlatform(state.config.process.platform) )        _exit(result);#endif    state.libSystemHelpers->exit(result);}

  • 走全部的 fixups chains 和 rebase dyld


  • mach消息初始化:mach_init()
  • 栈溢出掩护:__guard_setup(kernArgs->findApple());
  • 构建历程设置:config = ProcessConfig(kernArgs, sSyscallDelegate);
class VIS_HIDDEN ProcessConfig{public:                            // used in unit tests to config and test ProcessConfig objects                            ProcessConfig(const KernelArgs* kernArgs, SyscallDelegate&);#if !BUILDING_DYLD    void                    reset(const MachOAnalyzer* mainExe, const char* mainPath, const DyldSharedCache* cache);#endif    //    // Contains config info derived from Kernel arguments    //    class Process    {    public:                                    Process(const KernelArgs* kernArgs, SyscallDelegate&);        const MachOAnalyzer*        mainExecutable;        const char*                 mainExecutablePath;        const char*                 mainUnrealPath;             // raw path used to launch        uint32_t                    mainExecutableSDKVersion;        uint32_t                    mainExecutableSDKVersionSet;        uint32_t                    mainExecutableMinOSVersion;        uint32_t                    mainExecutableMinOSVersionSet;        dyld3:latform             basePlatform;        dyld3:latform             platform;        const char*                 dyldPath;        int                         argc;        const char* const*          argv;        const char* const*          envp;        const char* const*          apple;        const char*                 progname;        DyldCommPage                commPage;        const GradedArchs*          archs;        int                         pid;        bool                        isTranslated;        bool                        catalystRuntime; // Mac Catalyst app or iOS-on-mac app        bool                        enableDataConst; // Temporarily allow disabling __DATA_CONST for bringup        bool                        proactivelyUseWeakDefMap;        const char*                 appleParam(const char* key) const;        const char*                 environ(const char* key) const;        const char*                 strdup(const char*) const; // allocates into read-only region        void*                       roalloc(size_t) const;     // allocates into read-only region    private:        friend class ProcessConfig;        uint32_t                    findVersionSetEquivalent(dyld3:latform versionPlatform, uint32_t version) const;        const char*                 pathFromFileHexStrings(SyscallDelegate& sys, const char* encodedFileInfo);        const char*                 getDyldPath(SyscallDelegate& sys);        const char*                 getMainPath(SyscallDelegate& syscall);        const char*                 getMainUnrealPath(SyscallDelegate& syscall);        dyld3:latform             getMainPlatform();        const GradedArchs*          getMainArchs(SyscallDelegate& osDelegate);        bool                        usesCatalyst();    };    //    // Contains security related config info    //    class Security    {    public:                                    Security(Process& process, SyscallDelegate&);        bool                        internalInstall;        bool                        allowAtPaths;        bool                        allowEnvVarsPrint;        bool                        allowEnvVarsPath;        bool                        allowEnvVarsSharedCache;        bool                        allowClassicFallbackPaths;        bool                        allowInsertFailures;        bool                        allowInterposing;        bool                        skipMain;     private:        uint64_t                    getAMFI(const Process& process, SyscallDelegate& syscall);        void                        pruneEnvVars(Process& process);   };    //    // Contains logging related config info    //    class Logging    {    public:                                    Logging(const Process& process, const Security& security, SyscallDelegate&);        bool                        libraries;        bool                        segments;        bool                        fixups;        bool                        initializers;        bool                        apis;        bool                        notifications;        bool                        interposing;        bool                        loaders;        bool                        searching;        bool                        env;        int                         descriptor;        bool                        useStderr;        bool                        useFile;     private:    };    //    // Contains dyld cache related config info    //    class DyldCache    {    public:                                    DyldCache(Process&, const Security&, const Logging&, SyscallDelegate&);        const DyldSharedCache*          addr;        uintptr_t                       slide;        const char*                     path;        const objc_opt:bjc_opt_t*     objCCacheInfo;        const SwiftOptimizationHeader*  swiftCacheInfo;        dyld3:latform                 platform;        uint32_t                        osVersion;        uint32_t                        dylibCount;        bool                        indexOfPath(const char* dylibPath, uint32_t& dylibIndex) const;        void                        makeDataConstWritable(const Logging&, const SyscallDelegate&, bool writable) const;    private:        friend class ProcessConfig;        bool                        uuidOfFileMatchesDyldCache(const Process& process, const SyscallDelegate& syscall, const char* path) const;        void                        setPlatformOSVersion(const Process& proc);        void                        setupDyldCommPage(Process& process, const Security& security, SyscallDelegate& syscall);    };    //    // Contains path searching config info    //    class PathOverrides    {    public:                                        PathOverrides(const Process&, const Security&, const Logging&, const DyldCache&, SyscallDelegate&);        enum Type { pathDirOverride, versionedOverride, suffixOverride, catalystPrefix, simulatorPrefix, rawPath,              rpathExpansion, loaderPathExpansion, executablePathExpansion, implictRpathExpansion, customFallback, standardFallback };        void                            forEachPathVariant(const char* requestedPath, dyld3:latform platform, bool disableCustomFallbacks, bool& stop,                                                           void (^handler)(const char* possiblePath, Type type, bool& stop)) const;        void                            forEachInsertedDylib(void (^handler)(const char* dylibPath, bool &stop)) const;        bool                            dontUsePrebuiltForApp() const;        bool                            hasInsertedDylibs() const { return (_insertedDylibCount != 0); }        uint32_t                        insertedDylibCount() const { return _insertedDylibCount; }        const char*                     simRootPath() const { return _simRootPath; }        static const char*              getLibraryLeafName(const char* path);        static const char*              typeName(Type);    private:        void                            setEnvVars(const char* envp[], const char* mainExePath);        void                            addEnvVar(const Process& process, const Security& security, const char* keyEqualsValue, bool isLC_DYLD_ENV, char* crashMsg);        void                            processVersionedPaths(const Process& proc, SyscallDelegate&, const DyldCache&, dyld3:latform, const GradedArchs&);        void                            forEachEnvVar(void (^handler)(const char* envVar)) const;        void                            forEachExecutableEnvVar(void (^handler)(const char* envVar)) const;        void                            setString(const Process& process, const char*& var, const char* value);        static void                     forEachInColonList(const char* list1, const char* list2, void (^callback)(const char* path, bool& stop));        const char*                     getFrameworkPartialPath(const char* path) const;        void                            handleListEnvVar(const char* key, const char** list, void (^handler)(const char* envVar)) const;        void                            handleEnvVar(const char* key, const char* value, void (^handler)(const char* envVar)) const;        void                            forEachDylibFallback(dyld3:latform platform, bool disableCustom, void (^handler)(const char* fallbackDir, Type type, bool& stop)) const;        void                            forEachFrameworkFallback(dyld3:latform platform, bool disableCustom, void (^handler)(const char* fallbackDir, Type type, bool& stop)) const;        void                            forEachImageSuffix(const char* path, Type type, bool& stop, void (^handler)(const char* possiblePath, Type type, bool& stop)) const;        void                            addSuffix(const char* path, const char* suffix, char* result) const;        void                            checkVersionedPath(const Process&, const char* path, SyscallDelegate& delegate, const DyldCache&, dyld3:latform platform, const GradedArchs& archs);        void                            addPathOverride(const Process&, const char* installName, const char* overridePath);        enum class FallbackPathMode { classic, restricted, none };        struct DylibOverride { DylibOverride* next; const char* installName; const char* overridePath; };        const char*                     _dylibPathOverridesEnv       = nullptr;        const char*                     _frameworkPathOverridesEnv   = nullptr;        const char*                     _dylibPathFallbacksEnv       = nullptr;        const char*                     _frameworkPathFallbacksEnv   = nullptr;        const char*                     _versionedDylibPathsEnv      = nullptr;        const char*                     _versionedFrameworkPathsEnv  = nullptr;        const char*                     _dylibPathOverridesExeLC     = nullptr;        const char*                     _frameworkPathOverridesExeLC = nullptr;        const char*                     _dylibPathFallbacksExeLC     = nullptr;        const char*                     _frameworkPathFallbacksExeLC = nullptr;        const char*                     _versionedFrameworkPathExeLC = nullptr;        const char*                     _versionedDylibPathExeLC     = nullptr;        const char*                     _insertedDylibs              = nullptr;        const char*                     _imageSuffix                 = nullptr;        const char*                     _simRootPath                 = nullptr;  // simulator only        DylibOverride*                  _versionedOverrides          = nullptr;  // linked list of VERSIONED overrides        FallbackPathMode                _fallbackPathMode            = FallbackPathMode::classic;        uint32_t                        _insertedDylibCount          = 0;    };    // wrappers for macOS that causes special three libsystem dylibs to not exist if they match what is in dyld cache    bool simulatorFileMatchesDyldCache(const char* path) const;    bool fileExists(const char* path, FileID* fileID=nullptr, bool* notAFile=nullptr) const;    // if there is a dyld cache and the supplied path is in the dyld cache at that path or a symlink, return canonical path    const char* canonicalDylibPathInCache(const char* dylibPath) const;    // all instance variables are organized into groups    SyscallDelegate         syscall;    Process                 process;    Security                security;    Logging                 log;    DyldCache               dyldCache;    PathOverrides           pathOverrides;};

  • 创建Allocator和APIs/RuntimeState对象: APIs& state = APIs::bootstrap(config, sLocks);

APIs继承自RuntimeState
class VIS_HIDDEN APIs : public RuntimeState{public:#if BUILDING_DYLD    static      APIs&                         bootstrap(const ProcessConfig& c, RuntimeLocks& locks);#else    static      APIs&                         bootstrap(const ProcessConfig& c);#endif    //    // private call from libdyld.dylib into dyld to tell that libSystem.dylib is initialized    //    virtual     void                        _libdyld_initialize(const LibSystemHelpers* helpers);    //    // APIs from macOS 10.2    //    virtual     uint32_t                    _dyld_image_count();    virtual     const mach_header*          _dyld_get_image_header(uint32_t index);    virtual     intptr_t                    _dyld_get_image_vmaddr_slide(uint32_t index);    virtual     const char*                 _dyld_get_image_name(uint32_t index);    virtual     void                        _dyld_register_func_for_add_image(void (*func)(const mach_header* mh, intptr_t vmaddr_slide));    virtual     void                        _dyld_register_func_for_remove_image(void (*func)(const mach_header* mh, intptr_t vmaddr_slide));    virtual     int32_t                     NSVersionOfLinkTimeLibrary(const char* libraryName);    virtual     int32_t                     NSVersionOfRunTimeLibrary(const char* libraryName);    virtual     int                         _NSGetExecutablePath(char* buf, uint32_t* bufsize);    virtual     void                        _dyld_fork_child();    //    // APIs from macOS 10.4    //    virtual     int                         dladdr(const void*, Dl_info* result);    virtual     void*                       dlopen(const char* path, int mode);    virtual     int                         dlclose(void* handle);    virtual     char*                       dlerror();    virtual     void*                       dlsym(void* handle, const char* symbol);    virtual     bool                        dlopen_preflight(const char* path);    //    // APIs deprecated in macOS 10.5 and not on any other platform    //    virtual     NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(const char* pathName, NSObjectFileImage* objectFileImage);    virtual     NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(const void* address, size_t size, NSObjectFileImage* objectFileImage);    virtual     bool                        NSDestroyObjectFileImage(NSObjectFileImage objectFileImage);    virtual     bool                        NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage, const char* symbolName);    virtual     void*                       NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage, const char* segmentName, const char* sectionName, size_t* size);    virtual     const char*                 NSNameOfModule(NSModule m);    virtual     const char*                 NSLibraryNameForModule(NSModule m);    virtual     NSModule                    NSLinkModule(NSObjectFileImage objectFileImage, const char* moduleName, uint32_t options);    virtual     bool                        NSUnLinkModule(NSModule module, uint32_t options);    virtual     bool                        NSIsSymbolNameDefined(const char* symbolName);    virtual     bool                        NSIsSymbolNameDefinedWithHint(const char* symbolName, const char* libraryNameHint);    virtual     bool                        NSIsSymbolNameDefinedInImage(const mach_header* image, const char* symbolName);    virtual     NSSymbol                    NSLookupAndBindSymbol(const char* symbolName);    virtual     NSSymbol                    NSLookupAndBindSymbolWithHint(const char* symbolName, const char* libraryNameHint);    virtual     NSSymbol                    NSLookupSymbolInModule(NSModule module, const char* symbolName);    virtual     NSSymbol                    NSLookupSymbolInImage(const mach_header* image, const char* symbolName, uint32_t options);    virtual     void*                       NSAddressOfSymbol(NSSymbol symbol);    virtual     NSModule                    NSModuleForSymbol(NSSymbol symbol);    virtual     void                        NSLinkEditError(NSLinkEditErrors* c, int* errorNumber, const char** fileName, const char** errorString);    virtual     bool                        NSAddLibrary(const char* pathName);    virtual     bool                        NSAddLibraryWithSearching(const char* pathName);    virtual     const mach_header*          NSAddImage(const char* image_name, uint32_t options);    virtual     bool                        _dyld_image_containing_address(const void* address);    virtual     void                        _dyld_lookup_and_bind(const char* symbol_name, void** address, NSModule* module);    virtual     void                        _dyld_lookup_and_bind_with_hint(const char* symbol_name, const char* library_name_hint, void** address, NSModule* module);    virtual     void                        _dyld_lookup_and_bind_fully(const char* symbol_name, void** address, NSModule* module);    //    // Added macOS 10.6    //    virtual     intptr_t                    _dyld_get_image_slide(const mach_header* mh);    virtual     const char*                 dyld_image_path_containing_address(const void* addr);#if !__USING_SJLJ_EXCEPTIONS__    virtual     bool                        _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info);#endif    //    // Added iOS 6, macOS 10.8    //    virtual     uint32_t                    dyld_get_sdk_version(const mach_header* mh);    virtual     uint32_t                    dyld_get_min_os_version(const mach_header* mh);    virtual     uint32_t                    dyld_get_program_sdk_version();    virtual     uint32_t                    dyld_get_program_min_os_version();    //    // Added iOS 7, macOS 10.9    //    virtual     bool                        dyld_process_is_restricted();    //    // Added iOS 8, macOS 10.10    //    virtual     bool                        dyld_shared_cache_some_image_overridden();    virtual     void                        _tlv_atexit(void (*termFunc)(void* objAddr), void* objAddr);    virtual     void                        _tlv_bootstrap();    virtual     void                        _tlv_exit();    //    // Added iOS 9, macOS 10.11, watchOS 2.0    //    virtual     int                         dyld_shared_cache_iterate_text(const uuid_t cacheUuid, void (^callback)(const dyld_shared_cache_dylib_text_info* info));    virtual     const mach_header*          dyld_image_header_containing_address(const void* addr);    virtual     const char*                 dyld_shared_cache_file_path();    virtual     uint32_t                    dyld_get_program_sdk_watch_os_version();    virtual     uint32_t                    dyld_get_program_min_watch_os_version();    //    // Added iOS 10, macOS 10.12, watchOS 3.0    //    virtual     void                        _dyld_objc_notify_register(_dyld_objc_notify_mapped, _dyld_objc_notify_init, _dyld_objc_notify_unmapped);    virtual     bool                        _dyld_get_image_uuid(const mach_header* mh, uuid_t uuid);    virtual     bool                        _dyld_get_shared_cache_uuid(uuid_t uuid);    virtual     bool                        _dyld_is_memory_immutable(const void* addr, size_t length);    virtual     int                         dyld_shared_cache_find_iterate_text(const uuid_t cacheUuid, const char* extraSearchDirs[], void (^callback)(const dyld_shared_cache_dylib_text_info* info));    //    // Added iOS 11, macOS 10.13, bridgeOS 2.0    //    virtual     const void*                 _dyld_get_shared_cache_range(size_t* length);    virtual     uint32_t                    dyld_get_program_sdk_bridge_os_version();    virtual     uint32_t                    dyld_get_program_min_bridge_os_version();    //    // Added iOS 12, macOS 10.14    //    virtual     dyld_platform_t             dyld_get_active_platform();    virtual     dyld_platform_t             dyld_get_base_platform(dyld_platform_t platform);    virtual     bool                        dyld_is_simulator_platform(dyld_platform_t platform);    virtual     bool                        dyld_sdk_at_least(const mach_header* mh, dyld_build_version_t version);    virtual     bool                        dyld_minos_at_least(const mach_header* mh, dyld_build_version_t version);    virtual     bool                        dyld_program_sdk_at_least(dyld_build_version_t version);    virtual     bool                        dyld_program_minos_at_least(dyld_build_version_t version);    virtual     void                        dyld_get_image_versions(const mach_header* mh, void (^callback)(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version));    virtual     void                        _dyld_images_for_addresses(unsigned count, const void* addresses[], dyld_image_uuid_offset infos[]);    virtual     void                        _dyld_register_for_image_loads(void (*func)(const mach_header* mh, const char* path, bool unloadable));    //    // Added iOS 13, macOS 10.15    //    virtual     void                        _dyld_atfork_prepare();    virtual     void                        _dyld_atfork_parent();    virtual     bool                        dyld_need_closure(const char* execPath, const char* dataContainerRootDir);    virtual     bool                        dyld_has_inserted_or_interposing_libraries(void);    virtual     bool                        _dyld_shared_cache_optimized(void);    virtual     bool                        _dyld_shared_cache_is_locally_built(void);    virtual     void                        _dyld_register_for_bulk_image_loads(void (*func)(unsigned imageCount, const mach_header* mhs[], const char* paths[]));    virtual     void                        _dyld_register_driverkit_main(void (*mainFunc)(void));    virtual     void                        _dyld_missing_symbol_abort();    virtual     const char*                 _dyld_get_objc_selector(const char* selName);    virtual     void                        _dyld_for_each_objc_class(const char* className, void (^)(void* classPtr, bool isLoaded, bool* stop));    virtual     void                        _dyld_for_each_objc_protocol(const char* protocolName, void (^)(void* protocolPtr, bool isLoaded, bool* stop));    //    // Added iOS 14, macOS 11    //    virtual     uint32_t                    _dyld_launch_mode();    virtual     bool                        _dyld_is_objc_constant(DyldObjCConstantKind kind, const void* addr);    virtual     bool                        _dyld_has_fix_for_radar(const char* rdar);    virtual     const char*                 _dyld_shared_cache_real_path(const char* path);    virtual     bool                        _dyld_shared_cache_contains_path(const char* path);    virtual     void*                       dlopen_from(const char* path, int mode, void* addressInCaller);#if !__i386__    virtual     void *                      dlopen_audited(const char * path, int mode);#endif    virtual     const struct mach_header*   _dyld_get_prog_image_header();    //    // Added iOS 15, macOS 12    //    virtual     void                                obsolete() __attribute__((noreturn));    virtual     void                                _dyld_visit_objc_classes(void (^callback)(const void* classPtr));    virtual     uint32_t                            _dyld_objc_class_count(void);    virtual     bool                                _dyld_objc_uses_large_shared_cache(void);    virtual     _dyld_protocol_conformance_result   _dyld_find_protocol_conformance(const void *protocolDescriptor,                                                                                    const void *metadataType,                                                                                    const void *typeDescriptor) const;    virtual     _dyld_protocol_conformance_result   _dyld_find_foreign_type_protocol_conformance(const void *protocol,                                                                                                 const char *foreignTypeIdentityStart,                                                                                                 size_t foreignTypeIdentityLength) const;    virtual     uint32_t                            _dyld_swift_optimizations_version() const;    virtual     void                                runAllInitializersForMain();    virtual     void                                _dyld_before_fork_dlopen();    virtual     void                                _dyld_after_fork_dlopen_parent();    virtual     void                                _dyld_after_fork_dlopen_child();private:#if BUILDING_DYLD                            APIs(const ProcessConfig& c, RuntimeLocks& locks, Allocator* alloc) : RuntimeState(c, locks, *alloc) {}#else                            APIs(const ProcessConfig& c, Allocator* alloc) : RuntimeState(c, *alloc) {}#endif    // internal helpers    uint32_t                getSdkVersion(const mach_header* mh);    dyld_build_version_t    mapFromVersionSet(dyld_build_version_t version);    uint32_t                linkedDylibVersion(const dyld3::MachOFile* mf, const char* installname);    uint32_t                deriveVersionFromDylibs(const dyld3::MachOFile* mf);    void                    forEachPlatform(const dyld3::MachOFile* mf, void (^callback)(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version));    uint32_t                basePlaform(uint32_t reqPlatform) const;    bool                    findImageMappedAt(const void* addr, const MachOLoaded** ml, bool* neverUnloads = nullptr, const char** path = nullptr, const void** segAddr = nullptr, uint64_t* segSize = nullptr, uint8_t* segPerms = nullptr);    void                    clearErrorString();    void                    setErrorString(const char* format, ...) __attribute__((format(printf, 2, 3)));    const Loader*           findImageContaining(void* addr);    bool                    flatFindSymbol(const char* symbolName, void** symbolAddress, const mach_header** foundInImageAtLoadAddress);    bool                    validLoader(const Loader* maybeLoader);    void                    forEachImageVersion(const mach_header* mh, void (^callback)(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version));};//// Note: need to force vtable ptr auth so that libdyld.dylib from base OS and driverkit use same ABI//class [[clang::ptrauth_vtable_pointer(process_independent, address_discrimination, type_discrimination)]] RuntimeState{public:    const ProcessConfig&            config;    Allocator&                      longTermAllocator;    const Loader*                   mainExecutableLoader = nullptr;    Vector<ConstAuthLoader>         loaded;    const Loader*                   libSystemLoader      = nullptr;    const Loader*                   libdyldLoader        = nullptr;    const void*                     libdyldMissingSymbol = 0;#if BUILDING_DYLD    RuntimeLocks&                   _locks;#endif    dyld4::ProgramVars*             vars                 = nullptr;    const LibSystemHelpers*         libSystemHelpers     = nullptr;    Vector<InterposeTupleAll>       interposingTuplesAll;    Vector<InterposeTupleSpecific>  interposingTuplesSpecific;    uint64_t                        weakDefResolveSymbolCount = 0;    WeakDefMap*                     weakDefMap                = nullptr;#if BUILDING_DYLD                                RuntimeState(const ProcessConfig& c, RuntimeLocks& locks, Allocator& alloc)#else                                RuntimeState(const ProcessConfig& c, Allocator& alloc = *Allocator::bootstrap())#endif                                    : config(c), longTermAllocator(alloc), loaded(&alloc),#if BUILDING_DYLD                                    _locks(locks),#endif                                    interposingTuplesAll(&alloc), interposingTuplesSpecific(&alloc),                                    _notifyAddImage(&alloc), _notifyRemoveImage(&alloc),                                    _notifyLoadImage(&alloc), _notifyBulkLoadImage(&alloc),                                    _tlvInfos(&alloc), _loadersNeedingDOFUnregistration(&alloc),                                    _missingFlatLazySymbols(&alloc), _dynamicReferences(&alloc),                                    _dlopenRefCounts(&alloc), _dynamicNeverUnloads(&alloc) {}    void                        setMainLoader(const Loader*);    void                        add(const Loader*);    MainFunc                    mainFunc()                   { return _driverKitMain; }    void                        setMainFunc(MainFunc func)   { _driverKitMain = func; }    void                        setDyldLoader(const Loader* ldr);    uint8_t*                    appState(uint16_t index);    uint8_t*                    cachedDylibState(uint16_t index);    const MachOLoaded*          appLoadAddress(uint16_t index);    void                        setAppLoadAddress(uint16_t index, const MachOLoaded* ml);    const MachOLoaded*          cachedDylibLoadAddress(uint16_t index);    void                        log(const char* format, ...) const __attribute__((format(printf, 2, 3))) ;    void                        vlog(const char* format, va_list list);    void                        setObjCNotifiers(_dyld_objc_notify_mapped, _dyld_objc_notify_init, _dyld_objc_notify_unmapped);    void                        addNotifyAddFunc(const Loader* callbackLoader, NotifyFunc);    void                        addNotifyRemoveFunc(const Loader* callbackLoader, NotifyFunc);    void                        addNotifyLoadImage(const Loader* callbackLoader, LoadNotifyFunc);    void                        addNotifyBulkLoadImage(const Loader* callbackLoader, BulkLoadNotifier);    void                        notifyObjCInit(const Loader* ldr);    void                        buildInterposingTables();    void                        withNotifiersReadLock(void (^work)());    void                        withNotifiersWriteLock(void (^work)());    void                        addPermanentRanges(const Array<const Loader*>& neverUnloadLoaders);    bool                        inPermanentRange(uintptr_t start, uintptr_t end, uint8_t* perms, const Loader** loader);    void                        notifyLoad(const dyld3::Array<const Loader*>& newLoaders);    void                        notifyUnload(const dyld3::Array<const Loader*>& removeLoaders);    void                        notifyDebuggerLoad(const Loader* oneLoader);    void                        notifyDebuggerLoad(const dyld3::Array<const Loader*>& newLoaders);    void                        notifyDebuggerUnload(const dyld3::Array<const Loader*>& removingLoaders);    void                        notifyDtrace(const dyld3::Array<const Loader*>& newLoaders);    void                        incDlRefCount(const Loader* ldr);  // used by dlopen    void                        decDlRefCount(const Loader* ldr);  // used by dlclose    void                        setLaunchMissingDylib(const char* missingDylibPath, const char* clientUsingDylib);    void                        setLaunchMissingSymbol(const char* missingSymbolName, const char* dylibThatShouldHaveSymbol, const char* clientUsingSymbol);    void                        addMissingFlatLazySymbol(const Loader* ldr, const char* symbolName, uintptr_t* bindLoc);    void                        rebindMissingFlatLazySymbols(const dyld3::Array<const Loader*>& newLoaders);    void                        removeMissingFlatLazySymbols(const dyld3::Array<const Loader*>& removingLoaders);    bool                        hasMissingFlatLazySymbols() const;    void                        addDynamicReference(const Loader* from, const Loader* to);    void                        removeDynamicDependencies(const Loader* removee);    void                        setSavedPrebuiltLoaderSet()      { _wrotePrebuiltLoaderSet = true; }    bool                        didSavePrebuiltLoaderSet() const { return _wrotePrebuiltLoaderSet; }    void                        setVMAccountingSuspending(bool mode);    bool                        hasOverriddenCachedDylib() { return _hasOverriddenCachedDylib; }    void                        setHasOverriddenCachedDylib() { _hasOverriddenCachedDylib = true; }    pthread_key_t               dlerrorPthreadKey() { return _dlerrorPthreadKey; }    typedef void  (*TLV_TermFunc)(void* objAddr);    void                        initialize();    void                        setUpTLVs(const MachOAnalyzer* ma);    void                        addTLVTerminationFunc(TLV_TermFunc func, void* objAddr);    void                        exitTLV();    void                        withLoadersReadLock(void (^work)());    void                        withLoadersWriteLock(void (^work)());    void                        incWritable();    void                        decWritable();    void                        initializeClosureMode();    const PrebuiltLoaderSet*    processPrebuiltLoaderSet() const { return _processPrebuiltLoaderSet; }    const PrebuiltLoaderSet*    cachedDylibsPrebuiltLoaderSet() const { return _cachedDylibsPrebuiltLoaderSet; }    uint8_t*                    prebuiltStateArray(bool app) const { return (app ? _processDylibStateArray : _cachedDylibsStateArray); }    const PrebuiltLoader*       findPrebuiltLoader(const char* loadPath) const;    bool                        saveAppClosureFile() const { return _saveAppClosureFile; }    bool                        failIfCouldBuildAppClosureFile() const { return _failIfCouldBuildAppClosureFile; }    bool                        saveAppPrebuiltLoaderSet(const PrebuiltLoaderSet* pblset) const;    bool                        inPrebuiltLoader(const void* p, size_t len) const;#if !BUILDING_DYLD    void                        resetCachedDylibs(const PrebuiltLoaderSet* dylibs, uint8_t* stateArray);    void                        setProcessPrebuiltLoaderSet(const PrebuiltLoaderSet* appPBLS);    void                        resetCachedDylibsArrays();#endif    // this need to be virtual to be callable from libdyld.dylb    virtual void                _finalizeListTLV(void* l);    virtual void*               _instantiateTLVs(pthread_key_t key);protected:    // Helpers to reset locks across fork()    void                        takeLockBeforeFork();    void                        releaseLockInForkParent();    void                        resetLockInForkChild();    void                        takeDlopenLockBeforeFork();    void                        releaseDlopenLockInForkParent();    void                        resetDlopenLockInForkChild();private:    //    // The PermanentRanges structure is used to make dyld_is_memory_immutable()    // fast and lock free. The table contains just ranges of memory that are in    // images that will never be unloaded.  Dylibs in the dyld shared cache are    // never in this table. A PermanentRanges struct is allocated at launch for    // app and its non-cached dylibs, because they can never be unloaded. Later    // if a dlopen() brings in non-cached dylibs which can never be unloaded,    // another PermanentRanges is allocated with the ranges brought in by that    // dlopen.  The PermanentRanges struct are chained together in a linked list    // with state._permanentRanges pointing to the start of the list.    // Because these structs never change, they can be read without taking a lock.    // That makes finding immutable ranges lock-less.    //    class PermanentRanges    {    public:        static PermanentRanges* make(RuntimeState& state, const Array<const Loader*>& neverUnloadLoaders);        bool                    contains(uintptr_t start, uintptr_t end, uint8_t* perms, const Loader** loader) const;        PermanentRanges*        next() const;        void                    append(PermanentRanges*);    private:        void                addPermanentRange(uintptr_t start, uintptr_t end, bool immutable, const Loader* loader);        void                add(const Loader*);        struct Range        {            uintptr_t      start;            uintptr_t      end;            const Loader*  loader;            uintptr_t      permissions;        };        // FIXME: we could pack this structure better to reduce memory usage        std::atomic<ermanentRanges*>   _next       = nullptr;        uintptr_t                       _rangeCount = 0;        Range                           _ranges[1];    };    // keep dlopen counts in a side table because it is rarely used, so it would waste space for each Loader object to have its own count field    friend class Reaper;    friend class RecursiveAutoLock;    struct DlopenCount {        const Loader*  loader;        uintptr_t      refCount;    };    // when a thread_local is first accessed on a thread, the thunk calls into dyld    // to allocate the variables.  The pthread_key is the index used to find the    // TLV_Info which then describes how much to allocate and how to initalize that memory.    struct TLV_Info    {        const MachOAnalyzer*    ma;        pthread_key_t           key;        uint32_t                initialContentOffset;        uint32_t                initialContentSize;    };    // used to record _tlv_atexit() entries to clean up on thread exit    struct TLV_Terminator    {        TLV_TermFunc  termFunc;        void*         objAddr;    };    struct TLV_TerminatorList {        TLV_TerminatorList* next  = nullptr;        uintptr_t           count = 0;        TLV_Terminator      elements[7];        void                reverseWalkChain(void (^work)(TLV_TerminatorList*));    };    struct RegisteredDOF    {        const Loader*   ldr;        int             registrationID;    };    struct MissingFlatSymbol    {        const Loader*   ldr;        const char*     symbolName;        uintptr_t*      bindLoc;    };    struct DynamicReference    {        const Loader*   from;        const Loader*   to;    };    struct HiddenCacheAddr { const void* cacheAddr; const void* replacementAddr; };    enum { kMaxBootTokenSize = 128 };    void                        appendInterposingTuples(const Loader* ldr, const uint8_t* dylibTuples, uint32_t tupleCount);    void                        garbageCollectImages();    void                        garbageCollectInner();    void                        removeLoaders(const dyld3::Array<const Loader*>& loadersToRemove);    void                        withTLVLock(void (^work)());    void                        setUpLogging();    void                        buildAppPrebuiltLoaderSetPath(bool createDirs);    bool                        fileAlreadyHasBootToken(const char* path, const Array<uint8_t>& bootToken) const;    bool                        buildBootToken(dyld3::Array<uint8_t>& bootToken) const;    void                        loadAppPrebuiltLoaderSet();    bool                        allowOsProgramsToSaveUpdatedClosures() const;    bool                        allowNonOsProgramsToSaveUpdatedClosures() const;    void                        allocateProcessArrays(uintptr_t count);    void                        checkHiddenCacheAddr(const Loader* t, const void* targetAddr, const char* symbolName, dyld3::OverflowSafeArray<HiddenCacheAddr>& hiddenCacheAddrs) const;        _dyld_objc_notify_mapped        _notifyObjCMapped       = nullptr;    _dyld_objc_notify_init          _notifyObjCInit         = nullptr;    _dyld_objc_notify_unmapped      _notifyObjCUnmapped     = nullptr;    Vector<NotifyFunc>              _notifyAddImage;    Vector<NotifyFunc>              _notifyRemoveImage;    Vector<LoadNotifyFunc>          _notifyLoadImage;    Vector<BulkLoadNotifier>        _notifyBulkLoadImage;    Vector<TLV_Info>                _tlvInfos;    Vector<RegisteredDOF>           _loadersNeedingDOFUnregistration;    Vector<MissingFlatSymbol>       _missingFlatLazySymbols;    Vector<DynamicReference>        _dynamicReferences;    const PrebuiltLoaderSet*        _cachedDylibsPrebuiltLoaderSet  = nullptr;    uint8_t*                        _cachedDylibsStateArray         = nullptr;    const char*                     _processPrebuiltLoaderSetPath   = nullptr;    const PrebuiltLoaderSet*        _processPrebuiltLoaderSet       = nullptr;    uint8_t*                        _processDylibStateArray         = nullptr;    const MachOLoaded**             _processLoadedAddressArray      = nullptr;    bool                            _saveAppClosureFile;    bool                            _failIfCouldBuildAppClosureFile;    PermanentRanges*                _permanentRanges          = nullptr;    MainFunc                        _driverKitMain            = nullptr;    Vector<DlopenCount>             _dlopenRefCounts;    Vector<const Loader*>           _dynamicNeverUnloads;    std::atomic<int32_t>            _gcCount                  = 0;    pthread_key_t                   _tlvTerminatorsKey        = 0;    pthread_key_t                   _dlerrorPthreadKey        = 0;    int                             _logDescriptor            = -1;    bool                            _logToSyslog              = false;    bool                            _logSetUp                 = false;    bool                            _hasOverriddenCachedDylib = false;    bool                            _wrotePrebuiltLoaderSet   = false;#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR    bool                            _vmAccountingSuspended    = false;#endif // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR};

  • 加载步伐的全部依靠项并将state绑定在一起:prepare(state, dyldMA);
  • 调用main(): appMain
12.png 2.prepare:加载步伐的全部依靠项

13.png

  • gProcessInfo 是存储dyld全部镜像信息的结构体:,生存着mach_header, dyld_uuid_info, dyldVersion等等信息。
gProcessInfo的声明:
struct dyld_all_image_infos* gProcessInfo = &dyld_all_image_infos;
struct dyld_all_image_infos {    uint32_t                        version;        /* 1 in Mac OS X 10.4 and 10.5 */    uint32_t                        infoArrayCount;#if defined(__cplusplus) && (BUILDING_LIBDYLD || BUILDING_DYLD)    std::atomic<const struct dyld_image_info*>  infoArray;#else    const struct dyld_image_info*    infoArray;#endif    dyld_image_notifier             notification;           bool                            processDetachedFromSharedRegion;    /* the following fields are only in version 2 (Mac OS X 10.6, iPhoneOS 2.0) and later */    bool                            libSystemInitialized;    const struct mach_header*       dyldImageLoadAddress;    /* the following field is only in version 3 (Mac OS X 10.6, iPhoneOS 3.0) and later */    void*                           jitInfo;    /* the following fields are only in version 5 (Mac OS X 10.6, iPhoneOS 3.0) and later */    const char*                     dyldVersion;    const char*                     errorMessage;    uintptr_t                       terminationFlags;    /* the following field is only in version 6 (Mac OS X 10.6, iPhoneOS 3.1) and later */    void*                           coreSymbolicationShmPage;    /* the following field is only in version 7 (Mac OS X 10.6, iPhoneOS 3.1) and later */    uintptr_t                       systemOrderFlag;    /* the following field is only in version 8 (Mac OS X 10.7, iPhoneOS 3.1) and later */    uintptr_t                       uuidArrayCount;    const struct dyld_uuid_info*    uuidArray;      /* only images not in dyld shared cache */    /* the following field is only in version 9 (Mac OS X 10.7, iOS 4.0) and later */    struct dyld_all_image_infos*    dyldAllImageInfosAddress;    /* the following field is only in version 10 (Mac OS X 10.7, iOS 4.2) and later */    uintptr_t                       initialImageCount;    /* the following field is only in version 11 (Mac OS X 10.7, iOS 4.2) and later */    uintptr_t                       errorKind;    const char*                     errorClientOfDylibPath;    const char*                     errorTargetDylibPath;    const char*                     errorSymbol;    /* the following field is only in version 12 (Mac OS X 10.7, iOS 4.3) and later */    uintptr_t                       sharedCacheSlide;    /* the following field is only in version 13 (Mac OS X 10.9, iOS 7.0) and later */    uint8_t                         sharedCacheUUID[16];    /* the following field is only in version 15 (macOS 10.12, iOS 10.0) and later */    uintptr_t                       sharedCacheBaseAddress;#if defined(__cplusplus) && (BUILDING_LIBDYLD || BUILDING_DYLD)    // We want this to be atomic in libdyld so that we can see updates when we map it shared    std::atomic<uint64_t>           infoArrayChangeTimestamp;#else    uint64_t                        infoArrayChangeTimestamp;#endif    const char*                     dyldPath;    mach_port_t                     notifyPorts[DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT];#if __LP64__    uintptr_t                       reserved[11-(DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT/2)];#else    uintptr_t                       reserved[9-DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT];#endif    // The following fields were added in version 18 (previously they were reserved padding fields)    uint64_t                        sharedCacheFSID;    uint64_t                        sharedCacheFSObjID;    /* the following field is only in version 16 (macOS 10.13, iOS 11.0) and later */    uintptr_t                       compact_dyld_image_info_addr;    size_t                          compact_dyld_image_info_size;    uint32_t                        platform; // FIXME: really a dyld_platform_t, but those aren't exposed here.    /* the following field is only in version 17 (macOS 10.16) and later */    uint32_t                          aotInfoCount;    const struct dyld_aot_image_info* aotInfoArray;    uint64_t                          aotInfoArrayChangeTimestamp;    uintptr_t                         aotSharedCacheBaseAddress;    uint8_t                           aotSharedCacheUUID[16];};

  • 举行pre-build, 创建 mainLoader镜像装载器
    ps : 假如熟悉dyld3的小搭档知道, 旧版本是创建一个ImageLoader镜像装载器
14.png

  • 创建just-in-time
    是dyld4一个新特性, dyld4在生存了dyld3的 mach-o 剖析器根本上,同时也引入了 just-in-time 的加载器来优化。
dyld3 出于对启动速率的优化的目标, 增长了预构建(闭包)。App第一次启动大概App发生厘革时会将部门启动数据创建为闭包存到当地,那么App下次启动将不再重新剖析数据,而是直接读取闭包内容。当然条件是应用步伐和体系应很少发生厘革,但假如这两者经常厘革等, 就会导闭包丢失或失效。
dyld4 采取了 pre-build + just-in-time 的双剖析模式,预构建 pre-build 对应的就是 dyld3 中的闭包,just-in-time 可以明白为及时剖析。当然just-in-time 也是可以利用 pre-build 的缓存的,以是性能可控。有了just-in-time, 目前应用初次启动、体系版本更新、平凡启动,dyld4 则可以根据缓存是否有用去选择符合的模式举行剖析。

  • 装载uuid、动态库、可实行文件
记录插入信息, 遍历全部dylibs, 一些记录查抄操纵继承往下走

  • 插入缓存
Loader::applyInterposingToDyldCache的实现:
void Loader::applyInterposingToDyldCache(RuntimeState& state){    const DyldSharedCache* dyldCache = state.config.dyldCache.addr;    if ( dyldCache == nullptr )        return; // no dyld cache to interpose    if ( state.interposingTuplesAll.empty() )        return; // no interposing tuples    // make the cache writable for this block    DyldCacheDataConstScopedWriter patcher(state);    state.setVMAccountingSuspending(true);    for ( const InterposeTupleAll& tuple : state.interposingTuplesAll ) {        uint32_t imageIndex;        uintptr_t cacheOffsetOfReplacee = tuple.replacee - (uintptr_t)dyldCache;        if ( !dyldCache->addressInText(cacheOffsetOfReplacee, &imageIndex) )            continue;        // Convert from a cache offset to an image offset        uint64_t mTime;        uint64_t inode;        const dyld3::MachOAnalyzer* imageMA = (dyld3::MachOAnalyzer*)(dyldCache->getIndexedImageEntry(imageIndex, mTime, inode));        if ( imageMA == nullptr )            continue;        uint32_t dylibOffsetOfReplacee = (uint32_t)((dyldCache->unslidLoadAddress() + cacheOffsetOfReplacee) - imageMA->preferredLoadAddress());        dyldCache->forEachPatchableExport(imageIndex, ^(uint32_t dylibVMOffsetOfImpl, const char* exportName) {            // Skip patching anything other than this symbol            if ( dylibVMOffsetOfImpl != dylibOffsetOfReplacee )                return;            uintptr_t newLoc = tuple.replacement;            dyldCache->forEachPatchableUseOfExport(imageIndex, dylibVMOffsetOfImpl,                                                   ^(uint64_t cacheVMOffset, MachOLoaded::PointerMetaData pmd, uint64_t addend) {                uintptr_t* loc      = (uintptr_t*)((uintptr_t)dyldCache + cacheVMOffset);                uintptr_t  newValue = newLoc + (uintptr_t)addend;    #if __has_feature(ptrauth_calls)                if ( pmd.authenticated ) {                    newValue = dyld3::MachOLoaded::ChainedFixupPointerOnDisk::Arm64e::signPointer(newValue, loc, pmd.usesAddrDiversity, pmd.diversity, pmd.key);                    *loc     = newValue;                    if ( state.config.log.interposing )                        state.log("interpose: *%p = %p (JOP: diversity 0x%04X, addr-div=%d, key=%s)\n",                                  loc, (void*)newValue, pmd.diversity, pmd.usesAddrDiversity, MachOLoaded::ChainedFixupPointerOnDisk::Arm64e::keyName(pmd.key));                    return;                }    #endif                if ( state.config.log.interposing )                    state.log("interpose: *%p = 0x%0llX (dyld cache patch) to %s\n", loc, newLoc + addend, exportName);                *loc = newValue;            });        });    }    state.setVMAccountingSuspending(false);}接下来的工作是一些其他关照和写入操纵。

  • 运行初始化方法
    // 运行全部的初始化    state.runAllInitializersForMain();3.runAllInitializersForMain:运行初始化方法

// 这是从dyldMain.cpp中提取出来的,以支持利用crt1.o的旧macOS应用步伐void APIs::runAllInitializersForMain(){    // 起首运行libSystem的初始化器    const_cast<Loader*>(this->libSystemLoader)->beginInitializers(*this);    this->libSystemLoader->runInitializers(*this);    gProcessInfo->libSystemInitialized = true;    // 在运行libSystem的初始化器后,告诉objc在libSystem的子dylibs上运行任何+load方法    this->notifyObjCInit(this->libSystemLoader);    // <rdar://problem/32209809> 调用'init'函数对全部已经init'ed的图像 (below libSystem)    // 利用下标举行迭代,以便在+加载dloopen时数组不会在我们下面增长    for ( uint32_t i = 0; i != this->loaded.size(); ++i ) {        const Loader* ldr = this->loaded;        if ( ldr->analyzer(*this)->isDylib() && (strncmp(ldr->analyzer(*this)->installName(), "/usr/lib/system/lib", 19) == 0) ) {            // 查抄安装名称而不是路径,以处置惩罚libsystem子dylibs的DYLD_LIBRARY_PATH覆盖            const_cast<Loader*>(ldr)->beginInitializers(*this);            this->notifyObjCInit(ldr);        }    }    // 自底向上运行全部其他初始化器,起首运行插入的dylib初始化器    // 利用下标举行迭代,以便在初始化式dloopen时数组不会在下面增长    for ( uint32_t i = 0; i != this->loaded.size(); ++i ) {        const Loader* ldr = this->loaded;        ldr->runInitializersBottomUpPlusUpwardLinks(*this);        // stop as soon as we did main executable        // normally this is first image, but if there are inserted N dylibs, it is Nth in the list        if ( ldr->analyzer(*this)->isMainExecutable() )            break;    }}

  • 运行libSystem的初始化器


  • 告诉objc在libSystem的子dylibs上运行全部的+load方法
    (可实行文件、动态库等等上面的load)
    20.png
notifyObjCInit 这个工作在第4部门介绍

  • link 动态库和主步伐: runInitializersBottomUpPlusUpwardLinks
runInitializersBottomUpPlusUpwardLinks 这个工作在第5部门介绍
4.notifyObjCInit

在libSystem的初始化时,在其子dylibs上必要关照objc运行全部的+load方法
22.png notifyObjCInit的界说是在RuntimeState类的声明里:
23.png _dyld_objc_notify_init 在setObjCNotifiers被赋值的:
那setObjCNotifiers是在_dyld_objc_notify_register被调用的
而_dyld_objc_notify_register是在objc4源码里的 objc_init()里被调用的
26.png 末了objc_init()在库初始化时间之前由libSystem调用。
ps: load_images的内容在下章节,知道它是用来举行加载和调用+load方法就够了。
5.link 动态库和主步伐: runInitializersBottomUpPlusUpwardLinks

void Loader::runInitializersBottomUpPlusUpwardLinks(RuntimeState& state) const{    //state.log("runInitializersBottomUpPlusUpwardLinks() %s\n", this->path());    state.incWritable();    // 递归地运行全部初始化器 initializers    STACK_ALLOC_ARRAY(const Loader*, danglingUpwards, state.loaded.size());    this->runInitializersBottomUp(state, danglingUpwards);    //state.log("runInitializersBottomUpPlusUpwardLinks(%s), found %d dangling upwards\n", this->path(), danglingUpwards.count());    // 返回全部向上链接的image,并查抄它们是否已初始化 (might be danglers)    STACK_ALLOC_ARRAY(const Loader*, extraDanglingUpwards, state.loaded.size());    for ( const Loader* ldr : danglingUpwards ) {        //state.log("running initializers for dangling upward link %s\n", ldr->path());        ldr->runInitializersBottomUp(state, extraDanglingUpwards);    }    if ( !extraDanglingUpwards.empty() ) {        // 假如有两个向上悬空的image,请再次查抄初始化器initializers        danglingUpwards.resize(0);        for ( const Loader* ldr : extraDanglingUpwards ) {            //state.log("running initializers for dangling upward link %s\n", ldr->path());            ldr->runInitializersBottomUp(state, danglingUpwards);        }    }    state.decWritable();}runInitializersBottomUp
void Loader::runInitializersBottomUp(RuntimeState& state, Array<const Loader*>& danglingUpwards) const{    // 假如已经初始化器已经运行就什么都不做    if ( (const_cast<Loader*>(this))->beginInitializers(state) )        return;    //state.log("runInitializersBottomUp(%s)\n", this->path());    // 在运行我的初始化器之前,确保这个image下面的全部东西都已初始化    const uint32_t depCount = this->dependentCount();    for ( uint32_t i = 0; i < depCount; ++i ) {        DependentKind childKind;        if ( Loader* child = this->dependent(state, i, &childKind) ) {            if ( childKind == DependentKind::upward ) {                // 向上添加到列表稍后处置惩罚                if ( !danglingUpwards.contains(child) )                    danglingUpwards.push_back(child);            }            else {                child->runInitializersBottomUp(state, danglingUpwards);            }        }    }    // tell objc to run any +load methods in this image (done before C++ initializers)    state.notifyObjCInit(this);    // run initializers for this image    this->runInitializers(state);}6.调起主步伐入口

在 prepare 函数调用末了返回的就是主步伐入口 MainFunc
在start函数里调用了主步伐入口
28.png 末了给个总结图

dyld4应用步伐加载流程图
dyld3应用步伐加载流程图:
30.png
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-22 23:28, Processed in 0.240078 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表