Instruments 符号化

996 阅读3分钟

Instruments 是 Apple 官方提供给开发者的性能分析、测试工具,常用于分析性能、稳定性相关的问题。

但在使用过程中可能会遇到地址没有被符号化的问题,如下系统库 CFNetwork 相关的堆栈地址并没有被符号化展示: image.png

关于符号化相关的官方详细介绍,可以查看 WWDC2021 视频:Symbolication: Beyond the basics

类型

符号化与调试信息息息相关,调试信息分为以下三种类型:

  • Function starts
  • Nlist symbol table
  • DWARF

image.png

Function starts

Function starts 仅提供函数对应的起始地址: image.png

Function starts 数据解析类似于 iOS 15 以前的 rebase & bind,通过压缩字节流解析。

通过 Function starts 信息,可以知道地址距离其所在函数的首地址的 offset(0x100003a68 是函数首地址,264 是 offset): image.png

Nlist symbol table

Nlist symbol table 是一个结构体,内部定义了获取函数地址和名称的相关信息: image.png

Nlist 包含了direct symbols 和 indirect symbols。fishhook 就是利用了 Nlist 信息获取到 indirect symbols 地址对应的符号名称进行匹配,进而替换函数指针完成 hook 逻辑的。

Nlist 信息不能提供函数文件名、行号以及编译时优化信息。这也是系统库符号化之后没有文件名、行号的原因: image.png

DWARF

DWARF(debugging with attributed record formats)是一种调试信息的存储格式,dSYM 文件和 Mach-O 库都可以包含 DWARF 信息: image.png

DWARF 除了支持函数地址、名称,还拥有文件名、行号以及编译优化(内联等)信息。Apple 推荐使用 dSYM 文件完成符号化,因为 dSYM 文件不仅拥有最丰富细节的调试信息,而且能够被 Xcode 以及 Instruments 良好支持。

那么如何解决 Instruments 使用过程中未能符号化的问题?

系统库

因为系统库并没有提供 dSYM 文件,所以需要使用系统库文件完成符号化。当 iPhone 设备连接到 Mac 时,系统会默认下载该设备对应的系统库文件,文件对应的目录:

$HOME/Library/Developer/Xcode/iOS DeviceSupport

image.png

如果没有对应的 iPhone 设备,也可以使用开源工具库 ipsw 下载。

非系统库

对应自己编译的库,可以将 Debug Information Format 设置为:DWARF with dSYM file: image.png

可以通过 symbols -uuid 命令,校验库文件与 dSYM 文件一致性: image.png

如果是非自己编译的库,尽量让其提供 dSYM 文件。

如果确定已经使用 dSYM 文件了,Instruments 堆栈信息仍未符号化,那么可以检查一下项目的 entitlements 和代码签名配置。

可以使用 codesign 命令行工具,验证是否拥有正确的代码签名配置: image.png

同时还需要检查本地开发的 entitlement 中是否包含了 get-task-allow 项,确保 code signing inject base entitlemens 值为 YES: image.png

配置

当我们已经拥有系统库文件以及 dSYM 文件时,可以在 Symbols 配置里指定路径: image.png

如果此时依然未能符号化,可以通过 Instrument->File->Symbols-> Add Symbols 配置:

image.png

image.png

image.png

可以指定具体的 dSYMs 文件夹或者库文件,需要注意的是当指定系统库文件时,系统库文件没有可执行权限的情况下,默认不能够选中: image.png

可以通过增加可执行文件解决:

chmod +x CFNetwork

image.png