07--应用加载01--应用加载流程[_dyld]

2020-07-21  本文已影响0人  修_远
TOC

应用程序加载

准备条件:dyld-732.8 源码

编译过程

源文件 -> 预编译 -> 编译 -> 汇编 -> 链接(.a/.lib.so) -> 可执行文件

编译过程 编译过程

静态库

在链接阶段,会将汇编生成的目标与引用的库一起链接打包到可执行文件中

静态库

动态库

程序编译并不会链接到目标代码中,而是在程序运行时才被载入

动态库

APP加载流程

APP加载流程
  1. APP启动
  2. 加载 libSystem
  3. Runtime 向 dyld 注册回调函数
  4. 加载新的 image(镜像文件)
  5. 执行 map_imagesload_images(执行这一步之后,会回到第4步之前,ImageLoader 加载 image)
  6. 调用 main 函数

_dyld 分析

程序加载的顺序

  1. load 方法
load方法
  1. load 前还有 _dyld_start
_dyld_start
  1. 找到 arm64 的流程
image

通过注释找到

call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
  1. 找到 start 源码
start 源码

5. 找到 main 源码

整个 main 函数在 5880-6365部分,接近500行代码

main 源码
  1. reloadAllImages
reloadAllImages
  1. instantiateFromLoadedImage
instantiateFromLoadedImage
  1. sniffLoadCommands
sniffLoadCommands

dyld 流程:main函数分析

应用程序的入口:dyld::_main uintptr_t start(...)

1. 环境变量相关处理

2. 加载共享缓存

checkSharedRegionDisable((dyld3::MachOLoaded*)mainExecutableMH,mainExecutableSlide);
mapSharedCache();

3. 将 dyld 本身添加到UUID列表

addDyldImageToUUIDList();

4. reloadAllImages:

  1. 实例化主程序:instantiateFromLoadedImage

    • ImageLoaderMachO::instantiateMainExecutable

      • sniffLoadCommands:确定此 mach-o 文件是否具有压缩的 LINKEDIT 以及 段数
      • addImage(image);
    • 内核会映射到主要可执行文件中。我们需要为已经映射到主可执行文件中的文件中的文件创建一个 ImageLoader *

  2. 加载任何插入的动态库

    loadInsertedDylib(*lib);
    
  3. 链接库

    • 遍历:sInsertedDylibCount
    • ImageLoader* image = sAllImages[i+1];
    • link(sMainExecutable, sEnv.DYLD_BIND_AT_LAUNCH, true, ImageLoader::RPathChain(NULL, NULL), -1);
    • this->recursiveApplyInterposing(context);:插入任何动态加载的镜像文件

5. 运行所有初始化程序

  1. initializeMainExecutable();

  2. runInitializers

  3. 初始化准备:processInitializers(images.count)

  4. 递归一个个开始初始化:images.images[i]->recursiveInitialization

  5. notifySingle 单个镜像通知-开始行动

    1. 获取镜像文件真实地址:(*sNotifyObjCInit)(image->getRealPath(), image->machHeader());
    2. 初始化objc通知


      初始化objc通知
    3. 遍历初始化 this->doInitialization(context);
      1. doImageInit(context);

        Initializer func = (Initializer)(((struct macho_routines_command*)cmd)->init_address + fSlide);
        libSystemInitialized; //libSystem 初始化必须提前
        
      2. C++函数处理

        doModInitFunctions(context);
        

6. 通知监听 dyld 的main

notifyMonitoringDyldMain();
上一篇 下一篇

猜你喜欢

热点阅读