如何从ELF文件中获取静态初始化全局变量的取值
结论
完全可以。只要这两个全局变量没有被编译器/链接器优化剔除(触发条件一般是开高等级优化且变量全程未被代码引用),无论是未链接的*.o目标文件,还是链接完成的可执行ELF文件,都能通过readelf、objdump这类标准二进制分析工具读到变量的初始化取值。
原理说明
两个变量都属于带非零初始值的全局变量,不会被分配到不存储实际内容、仅运行时清零的.bss段,而是会被放入ELF文件的.data段,初始值会直接硬编码在段的原始数据中,随ELF文件一同存储,不需要运行时计算生成。
具体读取方法
针对*.o目标文件
- 先查询符号表,确认两个变量的所属段和段内偏移:
输出中可以看到# 用objdump查符号 objdump -t test.o | grep -E "Label|Hash" # 也可以用readelf查符号 readelf -s test.o | grep -E "Label|Hash"Label和Hash都属于.data段,同时会标注各自在段内的偏移位置。 - 导出
.data段的完整内容查看取值:
输出内容中:# 用objdump导出.data段,同时显示十六进制和对应ASCII内容 objdump -s -j .data test.o # 用readelf导出.data段的十六进制内容 readelf -x .data test.o- 对应
Label偏移位置的4字节数据,按小端序解析就是1234(1234的十六进制为0x000004d2,小端存储为字节序列d2 04 00 00) - 紧随其后的连续字节就是
Hash数组的内容,直接看ASCII列就能读到明文字符串0x11231abc,末尾还能看到字符串结束符\0。
- 对应
针对链接生成的可执行文件
读取逻辑和目标文件完全一致:
- 先通过符号表查询两个变量的位置,注意可执行文件经过链接后,符号对应的是加载后的虚拟内存地址,同时也能算出在文件内的偏移。
- 同样导出
.data段的内容,对照偏移就能找到两个变量的初始值。注意:如果编译时开了
-O2/-O3等高等级优化,且两个变量在代码中从未被引用,链接器的--gc-sections优化可能会直接把这两个没用到的变量删掉,这种情况就无法在ELF文件中找到对应内容了。
内容的提问来源于stack exchange,提问作者Xiaoyong Guo
相关产品推荐
相关产品推荐

