本期概要
- 话题:dyld4 开源了。
- Tips:Fix iOS12 libswift_Concurrency.dylib crash bug
- 面试模块:Synchronized 源码解读
- 优秀博客:Swift Protocol 进阶
- 学习资料:南大软件分析课程,iOS 开发学习图谱
- 开发工具:贝尔实验室开发的有向图/无向图自动布局应用,支持 dot 脚本绘制结构图,流程图等。
本期话题
@zhangferry:Apple 最近开源了 dyld4 的代码。通过阅读它的 Readme 文档,我们可以大致了解到 dyld4 相对 dyld3 做的改进有哪些。dyld3 出于对启动速度的优化,增加了启动闭包。应用首启和发生变化时将一些启动数据创建为闭包存到本地,下次启动将不再重新解析数据,而是直接读取闭包内容。这种方法的理想情况是应用程序和系统应很少发生变化,因为如果这两者经常变化,即意味着闭包可能面临失效。为了应对这类场景,dyld4 采用了 Prebuilt + JustInTime 的双解析模式,Prebuild 对应的就是 dyld3 中的启动闭包场景,JustInTime 大致对应 dyld2 中的实时解析,JustInTime 过程是可以利用 Prebuild 的缓存的,所以性能也还可控。应用首启、包体或系统版本更新、普通启动,dyld4 将根据缓存有效与否选择合适的模式进行解析。
dyld3 在不使用启动闭包的情况下会 fallback 到 dyld2,两套代码分别在两边,不利于行为的统一和维护,dyld4 做了逻辑统一(@鹅喵 补充)。所以 dyld4 的设计目标是更优的兼容性和逻辑统一。
还有一点,细心的开发者还在 dyld4 源码里发现了 realityOS 及 realityOS_Sim 相关的代码注释。很大可能苹果的 VR/AR 设备已经准备差不多了,静待今年的 WWDC 吧。
地址:apple-oss-distributions/dyld
开发Tips
整理编辑:Hello World
iOS12 libswift_Concurrency.dylib crash 问题修复
最近很多朋友都遇到了 iOS12 上 libswift_Concurrency 的 crash 问题,Xcode 13.2 release notes 中有提到是 Clang 编译器 bug,13.2.1 release notes 说明已经修复,但实际测试并没有。
crash 的具体原因是 Xcode 编译器在低版本 iOS12 上没有将 libswiftConcurrency.dylib 库剔除,反而是将该库嵌入到 ipa 的 Frameworks 路径下,导致动态链接时 libswiftConcurrency 被链接引发 crash。
问题分析
通过报错信息 Library not loaded: /usr/lib/swift/libswiftCore.dylib
分析是动态库没有加载,提示是 libswiftConcurrency.dylib 引用了该库。iOS12 本不该链接这个库,崩溃后通过 image list
查看加载的镜像文件会找到 libswiftConcurrency 的路径是 ipa/Frameworks 下的,查询资料了解到是 Xcode13.2 及其以上版本在做 Swift Concurrency 向前兼容时出现的 bug
问题定位
在按照 Xcode 13.2 release notes 提供的方案,将 libswiftCore 设置为 weak 并指定 rpath 后,crash 信息变更,此时 error 原因是 ___chkstk_darwin
符号找不到;根据 error Referenced from 发现还是 libswift_Concurrency 引用的,通过:
bash $ nm -u xxxAppPath/Frameworks/libswift_Concurrency.dylib
查看所有未定义符号(类型为 U), 其中确实包含了 ___chkstk_darwin
,13.2 release notes 中提供的解决方案只是设置了系统库弱引用,没有解决库版本差异导致的符号解析问题。
error 提示期望该符号应该在 libSystem.B.dylib 中,但是通过找到 libSystem.B.dylib 并打印导出符号:
bash $ nm -gAUj libSystem.B.dylib
发现即使是高版本的动态库中也并没有该符号,那么如何知道该符号在哪个库呢?这里用了一个取巧的方式,run iOS13 以上真机,并设置 symbol 符号 ___chkstk_darwin
, Xcode 会标记所有存在该符号的库,经过前面的思考,认为是在查找 libswiftCore 核心库时 crash 的可能性更大。
libSystem.B.dylib 路径在 ~/Library/Developer/Xcode/iOS DeviceSupport/xxversion/Symbols/usr/lib/ 目录下
如何校验呢,通过 Xcode 上 iOS12 && iOS13 两个不同版本的 libswiftCore.dylib 查看导出符号,可以发现,iOS12 上的 Core 库不存在,对比组 iOS13 上是存在的,所以基本可以断定 symbol not found 是这个原因造成的;当然你也可以把其他几个库也采用相同的方式验证。
通过在 ~/