背景
iOS & macOS 作为操作系统,其中内置了许多系统库(Library)。dyld_shared_cache,即动态库共享缓存。自 iOS 3.1 后,所有系统动态库被集合成一个 dyld_shared_cache 文件,以提升性能。
存放路径
为了研究dyld_shared_cache
,首先要找到其存在的路径。可以在 Apple 开源的 https://opensource.apple.com/tarballs/dyld/ 中的dyld_cache_format.h
文件中发现,其分别存放在 macOS 和 iOS 中的路径。
// This is the location of the macOS shared cache on macOS 11.0 and later
#define MACOSX_MRM_DYLD_SHARED_CACHE_DIR "/System/Library/dyld/"
#define IPHONE_DYLD_SHARED_CACHE_DIR "/System/Library/Caches/com.apple.dyld/"
dyld_shared_cache 存在于 iOS 设备的 /System/Library/Caches/com.apple.dyld/
目录。文件名即为 dyld_shared_cache_arm*
加上对应的架构编号。
从设备提取 dyld_shared_cache
- 如果 iOS 设备已经越狱,那么就可以直接从 /System/Library/Caches/com.apple.dyld/ 目录下找到,拷贝出来即可。
-
如果没有越狱设备,则可以巧妙地使用 Shortcuts(捷径)App 来获取。
- 添加操作:网页-->URL--从输入中获取URL--输入file:////System/Library/Caches/com.apple.dyld/
- 添加操作:文稿-->归档--制作归档
- 添加操作:共享-->系统--隔空投送
快捷指令运行后,将其 AirDrop 到 Mac 端,解压即可。
dyld_shared_cache共享缓存库,可以放到Hopper里查看所有的子库。
还原dyld_shared_cache
将库从 dyld_shared_cache 中还原,选取 Apple 开源 dyld 项目中的 dsc_extractor.cpp 来提取。
下载 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
如果不想自己编译,GitHub上有人提供了生成好的dsc_extractor可执行文件 https://github.com/macmade/dyld_cache_extract
Xcode连接真机后,会在/Users/CC/Library/Developer/Xcode/iOS\ DeviceSupport/14.4.1\ (18D61)\ arm64e/Symbols/System/Library/下有PrivateFrameworks和Frameworks(不用分解缓存库)
dyld_shared_cache存在的好处
在搭载 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。可以看出系统库在逐渐增大,这其中包括新增的 SDK 等。如果不进行整合,系统加载类库每次都需要检索所有需要的动态库,App 的启动时间会剧增。而整合为单一文件,程序启动的压力便会小很多,启动速度和性能便有所提升。