四、dyld启动app的过程

  • 基于dyld-851.27objc4-818.2 版本

  • 源码下载地址

  • 配置一系列环境变量:rebase dyld等

    • 加载共享缓存 mapSharedCache-> loadDyldCache

    • 判断根据dyld3(闭包模式)还是dyld2加载主程序

      • 闭包模式:缓存中找闭包,然后验证闭包,验证不成功,再继续缓存中找闭包,还是找不到,就创建一个闭包,接着启动闭包模式,如果启动不成功,或者闭包模式过期等等,再创建一次闭包,有了闭包,直接return主程序的main
    • 实例化主程序 instantiateFromLoadedImage->instantiateMainExecutable->sniffLoadCommands->addImage(segCount不能大于255个,libCount不能大于4095个,放入allimages数组里的第一位)

    • 加载插入动态库 loadInsertedDylib->load(越狱环境可修改变量DYLD_INSERT_LIBRARIES,来添加插件)

    • 链接主程序:linkingMainExecutable,rebase主程序

    • 链接动态库:link

    • 绑定符号:no-lazy表、weak表(lazy表是运行时用到的时候才绑定的)

    • 初始化主程序:initializeMainExecutable

      • runInitializers
        • processInitializers
          • recursiveInitialization
            • notifySingle(到这里,就在也找不到怎么调用load_images,但是看到调用了一个block sNotifyObjCInit 是registerObjCNotifiers函数的第二个参数,跟踪registerObjCNotifiers,看下是谁调用registerObjCNotifiers传来的第二个参数是什么 ?找到_dyld_objc_notify_register调用的,全局查找是谁调用了_dyld_objc_notify_register,找不到,那么就给示例工程下符号断点:_dyld_objc_notify_register,看下是谁调用了_dyld_objc_notify_register,结果发现是libobjc.A.dylib`_objc_init:调用的,接着就去objc源码查看_objc_init函数的第二个参数是什么,在文件objc-os.mm找到了函数void _objc_init(void),看到了调用了 _dyld_objc_notify_register(&map_images, load_images, unmap_image);,所以第二个参数是调用了load_images,调用了call_load_methods。接着调用call_class_loads)
    • doInitialization->doModInitFunctions c++的全局函数定义

      • 拿到主程序的main函数入口:getEntryFromLC_MAIN
      • 进入主程序man函数

你可能感兴趣的:(四、dyld启动app的过程)