专注、坚持

谈谈 iOS 中的 dyld_shared_cache

2018.10.14 by kingcos
Date Notes Source Code
2019-06-11 更新 Shortcuts 相关 -
2018-12-12 补充 dyld_shared_cache 路径来源 system_cmds-805.220.1
2018-10-14 首次提交 dyld-551.4

What

iOS & macOS 作为操作系统,其中内置了许多系统库(Library)。dyld_shared_cache,即动态库共享缓存。自 iOS 3.1 后,所有系统动态库被集合成一个 dyld_shared_cache 文件,以提升性能。当然,macOS 也有 dyld_shared_cache,比较特别的是可以通过 update_dyld_shared_cache 更新。

man update_dyld_shared_cache

How

为了研究 dyld_shared_cache,首先要找到其存在的路径。可以在 Apple 开源的 system_cmds 中 dyld_shared_cache.c 文件中发现,其分别存放在 macOS 和 iOS 中的路径。

system_cmds

macOS 上的 dyld_shared_cache 和 iOS 不太相同,每种架构额外对应了一种 .map 文件。因为本文着重在于 iOS,读者想要了解 macOS 相关可以在 system_cmds 中自行检索。

dyld_shared_cache on macOS

dyld_shared_cache 存在于 iOS 设备的 /System/Library/Caches/com.apple.dyld/ 目录。文件名即为 dyld_shared_cache_arm* 加上对应的架构编号。

从设备提取 dyld_shared_cache

如果 iOS 设备已经越狱,那么就可以直接从 /System/Library/Caches/com.apple.dyld/ 目录下找到,拷贝出来即可。

iFunBox

而如果没有越狱设备,则可以巧妙地使用 Shortcuts(捷径,现改名为「快捷指令」)App 来获取,你可以直接使用我已经编辑好的 Shortcuts,运行后,将其 AirDrop 到 Mac 端,解压即可。

Shortcuts

提取 dyld_shared_cache

关于将库从 dyld_shared_cache 中还原的工具现在有很多,这里只选取了使用 Apple 开源 dyld 中 dsc_extractor.cpp 来提取。有关更加详细的提取,可以参考 Extracting libraries from dyld_shared_cache - zhuowei 一文。

下载 Apple Open Source 官网 dyld 代码,找到其中 dsc_extractor.cpp 文件,将其 main 函数上方的 #if 0 宏置为 #if 1,这样 main 函数才得以执行。

使用 macOS 自带的 clang++ 编译器即可编译:clang++ -o dsc_extractor ./dsc_extractor.cpp dsc_iterator.cpp

dsc_extractor

最后运行可执行文件,并带上 dyld_shared_cache_arm64 路径和要提取到的路径参数,即可,例如:./dsc_extractor dyld_shared_cache_arm64 ./frameworks

提取结果

Why

在搭载 iOS 9.0.1 的 iPhone 5s 上,dyld_shared_cache_armv7s 大小为 518.6 MB,dyld_shared_cache_arm64 大小为 619.9 MB。而自 iOS 11 开始全面弃用 32 位应用,因此搭载 iOS 12 的 iPhone X 上仅有 dyld_shared_cache_arm64,大小为 1.28 GB(在搭载 iOS 13 beta 的 iPhone X 上大小为 1.57 GB)。可以看出系统库在逐渐增大,这其中包括新增的 SDK 等。如果不进行整合,系统加载类库每次都需要检索所有需要的动态库,App 的启动时间会剧增。而整合为单一文件,程序启动的压力便会小很多,启动速度和性能便有所提升。

Reference