快速上手
本指南从零开始演示一次完整的符号化:构建一个小程序、生成调试信息,并将一个地址解析为函数和源码行。本指南假设你已经安装了 atosl。
1. 一次符号化的构成
要将地址转换为符号,atosl 需要三样东西:
- 一个带符号的对象(
-o)——可执行文件、目标文件(object file)、dSYM 载荷(payload),或一个.dSYMbundle。 - 一个加载地址(
-l)——镜像被映射到的地址。对于直接来自崩溃报告的值,这就是镜像在 “Binary Images” 部分中的加载地址。 - 一个或多个待解析的地址。
atosl -o <OBJECT> -l <LOAD_ADDRESS> <ADDRESS>...
2. 构建一个示例(macOS)
cat > sample.c <<'EOF'
#include <stdio.h>
__attribute__((noinline)) int compute(int n) {
int acc = 0;
for (int i = 0; i < n; i++) acc += i * i;
return acc;
}
int main(int argc, char **argv) {
printf("%d\n", compute(argc + 5));
return 0;
}
EOF
# 保留目标文件,以便 dsymutil 收集 DWARF。
clang -g -O1 -arch arm64 -c sample.c -o sample.o
clang -g -arch arm64 sample.o -o sample
dsymutil sample -o sample.dSYM
在 Linux 上,使用
gcc -g sample.c -o sample编译;DWARF 会被嵌入可执行文件中,因此你可以直接将-o指向sample。
3. 找到一个地址及其加载地址
# `compute` 的静态 VM 地址:
nm sample | grep compute
# 例如 0000000100000328 T _compute
# 对于未发生滑动(slid)的镜像,其 __TEXT vmaddr 即为自然的加载地址:
otool -l sample | awk '/segname __TEXT/{f=1} f&&/vmaddr/{print; exit}'
# 例如 vmaddr 0x0000000100000000
4. 符号化
atosl -o sample.dSYM -l 0x100000000 0x100000328
compute (in sample) (sample.c:4)
这与 Apple 的 atos 给出的答案相同:
atos -o sample.dSYM/Contents/Resources/DWARF/sample -l 0x100000000 0x100000328
# compute (in sample) (sample.c:4)
5. 一次解析多个地址
在一次调用中传入多个地址——对象只会被解析一次:
atosl -o sample.dSYM -l 0x100000000 0x100000328 0x100000360 0x1000003a0
每个地址按顺序产生一行输出。
6. 读懂输出
当 DWARF 源码信息可用时:
compute (in sample) (sample.c:4)
当仅有符号表可用时(例如被裁剪过的二进制):
compute (in sample) + 16
+ 16 是相对于匹配符号起始处的字节偏移。
当某个地址无法解析时:
N/A - failed to search symbol table