【发布时间】:2011-03-23 02:08:09
【问题描述】:
我在 Linux 中有一个二进制/库。如何确定它是用帧指针编译的?
【问题讨论】:
-
你查看反汇编的目标文件,看看它是否使用了帧指针。不幸的是,我不记得那是什么样子了,所以这不是一个真正的答案。
-
为了澄清反汇编:
objdump -d <libYourLibrary.so>可以解决问题,以防万一您正在寻找反汇编程序。
我在 Linux 中有一个二进制/库。如何确定它是用帧指针编译的?
【问题讨论】:
objdump -d <libYourLibrary.so> 可以解决问题,以防万一您正在寻找反汇编程序。
赞/黑翼:
使用/不使用帧指针优化编译一些简单的东西,并在反汇编输出上使用diff -u 提供了一些线索:
$ diff -u with*
--- with-fp 2011-03-23 09:49:29.366277002 +0000
+++ without-fp 2011-03-23 09:49:35.046277002 +0000
@@ -5,14 +5,12 @@
Disassembly of section .text:
00000000 <func>:
- 0: 55 push %ebp
+ 0: 53 push %ebx
1: 31 c0 xor %eax,%eax
- 3: 89 e5 mov %esp,%ebp
- 5: 53 push %ebx
- 6: 81 ec 00 04 00 00 sub $0x400,%esp
- c: 8b 4d 08 mov 0x8(%ebp),%ecx
- f: 8d 9d fc fb ff ff lea -0x404(%ebp),%ebx
- 15: 8d 76 00 lea 0x0(%esi),%esi
+ 3: 81 ec 00 04 00 00 sub $0x400,%esp
+ 9: 8b 8c 24 08 04 00 00 mov 0x408(%esp),%ecx
+ 10: 89 e3 mov %esp,%ebx
+ 12: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
18: 8b 14 81 mov (%ecx,%eax,4),%edx
1b: 89 14 83 mov %edx,(%ebx,%eax,4)
1e: 83 c0 01 add $0x1,%eax
@@ -28,5 +26,4 @@
3e: 75 f0 jne 30 <func+0x30>
40: 81 c4 00 04 00 00 add $0x400,%esp
46: 5b pop %ebx
- 47: 5d pop %ebp
- 48: c3 ret
+ 47: c3 ret
您会看到多种变化:
push %ebp 和 mov %esp, %ebp。%ebp 注册任何东西)有push %ebp,但不会有@ 987654327@ 1,因为不需要初始化帧指针。mov 0x8(%ebp), %ecx。mov 0x408(%esp), %ecx。lea -0x404(%ebp), %ebx,而没有帧指针的代码为mov %esp, %ebx(可能是lea 0x0(%esp), %ebx)。%ebp 寄存器作为局部变量时(所示示例未显示) 编译器优化级别对生成的代码的实际外观有相当大的影响,但提到的这些特定项目(mov %esp, %ebp 和使用%ebp-参数/局部变量的相对寻址)仅 em> 曾在使用帧指针的代码中发现过,如果您使用 -fomit-frame-pointer 编译则会丢失。
【讨论】:
-fomit-frame-pointer 的编译器输出中,某些函数仍将使用%ebp 作为帧指针。堆栈上的 C99 可变长度数组会发生这种情况。我认为主要原因是用于异常处理/调试的堆栈展开数据无法处理可变大小的堆栈帧。也可以看到与超过 16B 对齐的本地数组/对象,因为 gcc / clang 使用 and $-32, %rsp 来实现它。
x86_64 的用户,要查找的寄存器是64 位等效项:%rbp 和%rsp - 概念是一样的!
gcc 和clang(UN*X 平台上的两个常见编译器)不会将创建的目标文件注释为“[not] using framepointers”。
mov %esp, 20(%ebp, %eax) 将匹配您的正则表达式 - 但绝对不是帧指针使用的指示。我同意“如果该计数很高”(例如,所有指令的一千分之一,按顺序排列),这很有可能。对该正则表达式的一次点击不一定是决定性的。