对于特定的目标文件,有两种方法可以做到这一点:
- 该
-ffunction-sections
选项gcc
指示它为正在编译的源文件中的每个函数创建一个单独的 ELF 部分。
- 符号表包含给定函数的节名、起始地址和大小;可以
objdump
通过--start-address
/--stop-address
参数输入。
第一个例子:
$ readelf -S 到 | grep '.text.'
[1] .text PROGBITS 0000000000000000 00000040
[ 4] .text.foo PROGBITS 0000000000000000 00000040
[6] .text.bar 程序 0000000000000000 00000060
[ 9] .text.foo2 程序 0000000000000000 000000c0
[11] .text.munch 程序 0000000000000000 00000110
[14] .text.startup.mai 程序 0000000000000000 00000180
这已经编译,并且在我的目标文件中-ffunction-sections
有四个函数 , foo()
,和 。我可以像这样单独拆卸它们:bar()
foo2()
munch()
$ objdump -w -d --section=.text.foo 到
to:文件格式elf64-x86-64
.text.foo 部分的反汇编:
0000000000000000 <foo>:
0: 48 83 ec 08 sub $0x8,%rsp
4: 8b 3d 00 00 00 00 mov 0(%rip),%edi #a <foo+0xa>
a: 31 f6 xor %esi,%esi
c: 31 c0 xor %eax,%eax
e: e8 00 00 00 00 callq 13 <foo+0x13>
13: 85 c0 测试 %eax,%eax
15:75 01 jne 18 <foo+0x18>
17: 90 诺普
18: 48 83 c4 08 添加 $0x8,%rsp
1c:c3 retq
另一个选项可以像这样使用(nm
转储符号表条目):
$ nm -f sysv 到 | grep 栏
酒吧 |0000000000000020| T | 功能|0000000000000026| |.text
$ objdump -w -d --start-address=0x20 --stop-address=0x46 to --section=.text
to:文件格式elf64-x86-64
部分.text的反汇编:
0000000000000020 <条>:
20: 48 83 ec 08 sub $0x8,%rsp
24: 8b 3d 00 00 00 00 mov 0(%rip),%edi # 2a <bar+0xa>
2a: 31 f6 xor %esi,%esi
2c: 31 c0 xor %eax,%eax
2e: e8 00 00 00 00 callq 33 <bar+0x13>
33: 85 c0 测试 %eax,%eax
35:75 01 jne 38 <bar+0x18>
37:90 诺普
38: bf 3f 00 00 00 移动 $0x3f,%edi
3d: 48 83 c4 08 添加 $0x8,%rsp
41: e9 00 00 00 00 jmpq 46 <bar+0x26>
在这种情况下,未-ffunction-sections
使用该选项,因此该函数的起始偏移量不为零,并且不在其单独的部分中(而是在 中)。.text
反汇编目标文件时要小心...
这不完全是您想要的,因为对于目标文件,call
目标(以及全局变量的地址)没有被解析 - 您在这里看不到foo
调用printf
,因为在二进制级别上的解析只发生在链接时。装配源将call printf
在那里。这callq
实际上printf
是在目标文件中的信息,但与代码分开(它在所谓的重定位部分中,列出目标文件中要由链接器“修补”的位置);反汇编程序无法解决此问题。