如何通过解析ELF文件获取printf的.plt函数符号地址
如何从ELF文件中获取printf的PLT地址?
你已经发现readelf -s无法直接获取printf的PLT地址(因为printf是未定义符号,readelf -s只会显示其为UND,值为0),但可以通过以下几种方法从ELF文件中提取出目标PLT地址(比如你例子中的0x401030):
方法1:用objdump直接定位
objdump的反汇编输出会直接标注每个PLT条目的地址和符号名,执行以下命令即可快速找到:
objdump -d a.out | grep -w "printf@plt"
输出会类似:
0000000000401030 <printf@plt>:
其中0x401030就是你要的PLT地址。
方法2:结合readelf分析重定位表和PLT段
PLT条目和重定位表.rela.plt中的JUMP_SLOT类型重定位项一一对应,步骤如下:
- 查看
.rela.plt中printf对应的重定位项:
readelf -r a.out | grep printf
输出示例:
000000404018 000c00000007 R_X86_64_JUMP_SLOT 0000000000000000 printf@GLIBC_2.2.5 + 0
- 查看
.plt段的起始地址:
readelf -S a.out | grep .plt
输出示例:
[13] .plt PROGBITS 0000000000401020 00001020 0000000000000030 0000000000000010 AX 0 0 16
- 计算PLT地址:x86_64架构下,每个PLT函数条目占16字节,
.plt段的第一个16字节是通用桩代码,后续每个条目对应一个函数。如果printf是.rela.plt中的第一个函数重定位项(排除动态链接器的内部项),那么其PLT地址就是.plt起始地址 + 16,即0x401020 + 0x10 = 0x401030,和你程序输出一致。
方法3:手动解析ELF文件(适合编程实现)
如果需要自己写程序解析ELF文件获取该地址,核心步骤是:
- 读取ELF文件头,定位到程序头表,找到
.plt段的虚拟地址(p_vaddr)。 - 读取
.rela.plt重定位段,遍历其中的条目,找到符号名为printf的JUMP_SLOT类型项。 - 根据重定位项在
.rela.plt中的索引,计算PLT地址:plt_start + 16 + index * 16(x86_64架构),其中plt_start是.plt段的起始虚拟地址,前16字节是通用桩,每个函数条目占16字节。
内容的提问来源于stack exchange,提问作者Rtoax
相关产品推荐
相关产品推荐

