【iOS】动态链接器dyld

这篇具有很好参考价值的文章主要介绍了【iOS】动态链接器dyld。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考:认识 dyld :动态链接器

dyld简介

dyld(Dynamic Linker)是 macOS 和 iOS 系统中的动态链接器,它是负责在运行时加载和链接动态共享库(dylib)或可执行文件的组件。在 macOS 系统中,dyld 位于 D/usr/lib/dyld

dyld源码地址

dyld 2

dyld 2(Dynamic Linker 2)是 macOS 和 iOS 系统中的第二代动态链接器。它是前代 dyld 1的进化版本,在性能、功能和安全性方面都有所改进和优化。dyld 2 主要负责在运行时加载和链接动态共享库或可执行文件的组件,并使程序能够正确执行。

以下是 dyld 2 的一些主要特点和改进:

  • 它具有对 C++ 初始化程序语义的正确支持,扩展了 Mach-O 格式,并更新了 dyld ,以便有效支持的 C++ 库。
  • 支持更多的架构及平台。
    自从Power PC上 发布 dyld 2.0 以来,添加了 x86,x86 64 arm,arm64 等架构,支持了 iOS, tvOS, 和 watchOS 平台。
  • 通过多种方式提高了安全性。
    • Codesigning : 代码签名。为了提高应用程序的安全性,dyld 2 支持验证应用程序和共享库的代码签名,以确保它们没有被篡改或恶意修改。
    • ASLR :Address space layout randomization 地址空间配置随机加载。
    • bounds checking:对 Mach-O Header 中的许多内容添加了重要的边界检查功能,从而可以避免恶意二进制数据的注入。
  • 模拟器支持:dyld 2 在 iOS 模拟器中提供了更好的性能和功能支持,使得开发者能够更方便地在模拟器上进行应用程序调试和测试。
  • 提升性能:使用 shared cache 技术完全替代了预绑定 prebinding。
  • 增量加载:dyld 2 支持增量加载(Incremental Loading),即在应用程序启动时,只加载必要的共享库和符号,而不是一次性加载所有动态库。这可以进一步减少启动时间和内存占用。
  • 并发加载:dyld 2 充分利用了多核处理器的优势,支持并发加载动态共享库,从而加速动态链接的过程。
  • 符号隔离:为了提高安全性,dyld 2 引入了符号隔离机制。它将共享库的符号表隔离起来,使得共享库之间的符号不会相互影响,从而避免符号冲突和符号泄

执行流程

【iOS】动态链接器dyld,ios,cocoa,macos

  1. dyld 2 初始化:一旦 dyld 2 加载到内存中,它会执行一些初始化操作,准备好执行动态链接的任务。主要代码在 dyldbootstrap::start,接着执行 dyld::_main dyld::_main 代码较多,是 dyld 加载的核心部分;
  2. 检查并准备环境,比如获取二进制路径,检查环境变量,解析主二进制的 image heade 等信息;
  3. 实例化主二进制的 image loader ,校验主二进制和 dyld 的版本是否匹配;
  4. 检查 shared cache 是否已经 map ,没有的话则先执行 map shared cache 操作;
  5. 检查 DYLD_INSERT_LIBRARIES,有的话则加载插入的动态库(实例化 image loader);
  6. 执行 link 操作。这个过程比较复杂,会先递归加载依赖的所有动态库(会对依赖库进行排序,被依赖的总是在前面),同时在这阶段将执行符号绑定,以及rebasebinding 操作;
  7. 执行初始化方法。Objective-C 的 +load 以及 C 的 constructor方法都会在这个阶段执行;
  8. 读取 Mach-O 的 LC_MAIN段 获取程序的入口地址,调用 main 方法。

加载共享缓存

因为 Foundation 还会依赖一些其他动态库,这些依赖的其他库还会再依赖更多的库,所以相互依赖的符号会很多,需要处理的时间也会比较长。这里系统上的动态链接器会使用共享缓存,共享缓存在 /var/db/dyld/。当加载 Mach-O 文件时,动态链接器会先检查是否有共享缓存。每个进程都会在自己的地址空间映射这些共享缓存,这样做可以起到优化 App 启动速度的作用。

加载共享缓存(Shared Cache)是 dyld 2 在 macOS 和 iOS 系统中用于加快动态链接的一项优化技术。共享缓存是一种预先生成的动态库集合,包含了多个应用程序常用的动态共享库。当应用程序启动时,dyld 2 可以直接从共享缓存中加载所需的动态库,而无需再重新从磁盘上逐个加载动态库,从而加快应用程序的启动速度。

共享缓存的加载过程可以简要概括如下:

  1. 生成共享缓存:在系统安装或更新时,操作系统会预先生成一个共享缓存,其中包含了多个常用的系统动态共享库和框架。这个过程通常在设备首次启动、操作系统升级或开发者重新编译系统库时进行。
  2. 共享缓存路径:共享缓存被保存在系统文件中,其路径是 /System/Library/Caches/com.apple.dyld/dyld_shared_cache_x86_64(macOS)/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64(iOS)等,具体路径会根据设备和架构而有所不同。
  3. 应用程序启动:当应用程序启动时,dyld 2 会首先检查共享缓存是否可用,并尝试加载共享缓存。
  4. 加载共享缓存:如果共享缓存可用,dyld 2 会直接将共享缓存映射到内存中,并建立共享缓存中动态库与应用程序之间的链接关系。
  5. 符号解析和重定位:在加载共享缓存后,dyld 2 会进行符号解析和重定位,将应用程序中的符号引用与共享缓存中的符号地址进行关联。
  6. 动态库链接:如果应用程序还依赖其他未包含在共享缓存中的动态共享库,dyld 2 会根据需要逐个加载这些动态共享库,并进行链接和符号解析。
  7. 应用程序初始化:一旦所有动态共享库都加载并完成符号解析后,dyld 2 会开始执行应用程序的main()函数,从而正式启动应用程序的执行。

动态库加载

链接的共用库分为静态库和动态库:

  • 静态库是编译时链接的库,需要链接进 Mach-O 文件里,如果需要更新就要重新编译一次,无法动态加载和更新;
  • 动态库是运行时链接的库,使用 dyld 就可以实现动态加载。

Mach-O 文件是编译后的产物,而动态库在运行时才会被链接,并没参与 Mach-O 文件的编译和链接,所以 Mach-O 文件中并没有包含动态库里的符号定义。也就是说,这些符号会显示为“未定义”,但它们的名字和对应的库的路径会被记录下来。运行时通过 dlopen 和 dlsym 导入动态库时,先根据记录的库路径找到对应的库,再通过记录的名字符号找到绑定的地址。

dlopen 会把共享库载入运行进程的地址空间,载入的共享库也会有未定义的符号,这样会触发更多的共享库被载入。dlopen 也可以选择是立刻解析所有引用还是滞后去做。dlopen 打开动态库后返回的是引用的指针,dlsym 的作用就是通过 dlopen 返回的动态库指针和函数符号,得到函数的地址然后使用。

dyld 2 存在的问题

  • Parse mach-o headers 可以使用撰改过的 Mach-O 文件头进行攻击,
  • Find dependencies 可以使用 @rpaths 即搜索路径。通过撰改这些路径或者将库插到适当的位置,可以破坏程序;
  • Perform symbol lookups 符号查找部分,因为在给定的库中,除非进行软件更新或者在磁盘上更改库,符号将始终位于库中的相同偏移位置;

dyld 3

dyld 3是全新的动态链接器,它完全改变了动态链接概念。WWDC-App Startup Time: Past, Present, and Future 提到在iOS 13系统中,iOS 全面采用新的 dyld 3 以替代之前版本的 dyld 2。dyld 3带来了可观的性能提升,减少了APP的启动时间。 因为 dyld 3 完全兼容 dyld 2,API 接口是一样的,所以在大部分情况下,开发者不需要做额外的适配就能平滑过渡。

执行流程

【iOS】动态链接器dyld,ios,cocoa,macos

dyld 3 包含这三个部分:

  1. 进程外 Mach-O 分析器和编译器 (out-of-process mach-o parser)由于 dyld 2 存在的问题,dyld 3 中将采用提前写入把结果数据缓存成文件的方式构成一个 lauch closure(可以理解为缓存文件)
  2. 进程内引擎 执行 launch closure 处理 (in-process engine)验证”lauch closures“是否正确,映射dylib,执行main函数。此时,它不再需要分析mach-o header和执行符号查找,节省了不少时间。
  3. launch closure 缓存服务 (launch closure cache )系统程序的 lauch closure 直接内置在 shared cache 中,而对于第三方APP,将在APP安装或更新时生成,这样就能保证 launch closure 总是在 APP 打开之前准备好。

大多数程序启动会使用缓存,而不需要调用进程外 mach-o分析器或编译器;并且 launch closure 比 Mach-O 更简单,它们是内存映射文件,不需要用复杂的方法进行分析,我们可以简单地验证它们,其作用是为了提高速度

dyld 3的符号缺失问题

dyld 2 默认采取的是 lazy symbol 的符号加载方式,但在 dyld 3中,在 App 启动之前,符号解析的结果已经在 lauch closure 内了,所以 lazy symbol 就不再需要。这时,如果有符号缺失的情况,APP 的行为会有不同:在 dyld 2 中,首次调用缺失符号时 APP 会 crash;而 dyld 3 中,缺失符号会导致 APP 一启动就会 crash。文章来源地址https://www.toymoban.com/news/detail-604418.html

到了这里,关于【iOS】动态链接器dyld的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【iOS内存管理-编译链接的过程】

    就我而言,iOS开发的过程中接触到的编译链接方面的知识很少,这部分知识还是很重要的。 对于iOS的编译链接过程来说并不难,和微机原理的汇编过程还是挺像的。今天对于编译链接的过程学习和了解一下。 参考:iOS程序员的自我修养-编译、链接过程 参考:iOS编译过程 计

    2024年02月16日
    浏览(41)
  • iOS/macOS - 逐行写入文件 (NSFileHandle)

    2024年02月15日
    浏览(45)
  • Charles证书过期解决方法macos/ios

    今天心血来潮打开Charles想试试看抓包手机APP(ios),结果发现各种x和提示ssl错误。开始以为是和魔法的代理冲突或者ip变了,捯饬很久后发现web的也报错。 然后搜了一会原因发现时证书过期了 1、搜索“钥匙串访问”,直接搜索“charles”,找到打叉的名称,直接删掉 2、打开

    2024年02月03日
    浏览(52)
  • iOS通用链接(UniversalLink)配置详细流程

    登录苹果账号后,点击创建的APP 的Bundle ID,跳转到APP 信息页面。 记录下 Team ID  和 Bundle ID  备用。 勾选上 功能列表上的 ”Associated Domains“选项。 配置苹果后台 创建一个text空文本文件,去掉文件后缀,命名为 apple-app-site-association (不能修改,且不能添加后缀)。 文件内添加

    2024年02月13日
    浏览(38)
  • XCODE IOS 静态链接库替换升级

    XCODE 版本15.2.  一个很久需求没更新的IOS 应用,近来有新需求要开发。 拉下代码运行,出现了个BAD_ACCESS错误。出错的位置位于一个调用的第三方的.a静态库内部。因为调用代码并没有修改,很容易想到可能XCODE相关升级,导致的问题。 由于是第三方的一个.a静态库,兼容问题

    2024年02月02日
    浏览(48)
  • iOS textView支持超链接跳转

    将某些文字变成高量可以点击的超链接核心功能代码 同时,要实现点击超链接的UITextView代理方法 完整代码 实现代理方法 效果图

    2024年02月12日
    浏览(36)
  • Charles 链接安卓和ios手机操作

    重点:手机和电脑在同一个Wi-Fi网络!!! 一、、安卓手机 设置 - 无线和网络 - WLAN 长按当前 WiFi - 修改网络 勾选显示高级选项 代理 - 手动 服务器主机名 - 填写 Mac 的IP 地址,服务器端口 - 默认:8888 Mac电脑 IP 获取方法:Charles - Help - Local IP Address   2、下载证书 打开手机浏

    2024年02月08日
    浏览(57)
  • iOS-配置Universal Links通用链接

    1、开启Associated Domains服务 登录苹果开发者网站,在 Certificates, Identifiers Profiles 页面左侧选择 Identifiers ,右侧选择对应的 App ID ,点击进入配置详情页,开启 Associated Domains 服务; 2、更新Profile文件(配置文件) 在 Certificates, Identifiers Profiles 页面左侧选择 Profiles ,右侧选择对

    2024年02月11日
    浏览(36)
  • uniapp 手动配置ios通用链接UniversalLink

    1.登录苹果开发者中心,找到对应的Identifier勾选 Associated Domains,重新生成profile文件 APP会在第一次启动的时候通过填写的域名来下载apple-app-site-association文件,先部署好文件后打开app 2.在uniapp的项目里面,创建apple-app-site-association文件, 切记不要有后缀名 teamid :是在苹果开发者中

    2024年02月15日
    浏览(45)
  • iOS Universal Links(通用链接)详细教程

    一:Universal Links是用来做什么的? iOS9.0推出的用于应用之间跳转的一种机, 通过一个https的链接启动app。如果手机有安装需要启动的app,可实现无缝跳转。如果没有安装,会打开网页。 实现场景:微信链接无缝跳转App, 网页链接无缝跳转App 移动端iOS实现: 1:找到app的Bu

    2024年03月15日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包