如何判断在Linux上是否使用帧指针编译二进制文件?

bla*_*ing 8 linux assembly

我在Linux中有一个二进制文件/库.如何确定使用帧指针编译它?

Fra*_*kH. 9

赞/黑翼:

使用/不使用framepointer优化编译一些简单的东西并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    
Run Code Online (Sandbox Code Playgroud)

您会看到多种更改:

  1. 与framepointers代码总是包含两者的两条指令push %ebp mov %esp, %ebp.
    Framepointer,更少的代码可能(,不中所示的情况,因为它是不使用%ebp任何东西寄存器)有push %ebp,但不会mov %esp, %ebp一个,因为它没有必要初始化framepointer.
  2. 带有framepointers的代码访问堆栈相对于framepointer的参数,mov 0x8(%ebp), %ecx如图所示.
    Framepointer-更少的代码这样做相对于stackpointer,用附加的偏移函数的的StackFrame的尺寸,等mov 0x408(%esp), %ecx.
    对于局部变量也是如此,在所示的代码中,lea -0x404(%ebp), %ebx对于没有帧指针的代码,帧代码使用代码与mov %esp, %ebx(可能已经lea 0x0(%esp), %ebx).
  3. 也有可能在两者之间的一些变化在寄存器分配,特别是如果代码变得复杂到足以使用所述%ebp寄存器的本地变量(示出的样品没有显示出)

编译器优化级别对生成的代码实际上看起来有多大影响但是这些特定的项目(mov %esp, %ebp以及%ebp对参数/局部变量使用-relative寻址)只能在使用framepointers的代码中找到,如果编译时丢失了-fomit-frame-pointer.

  • @kgibm 这太简单了。误报示例:“mov %esp, 20(%ebp, %eax)”将与您的正则表达式匹配 - 但绝对不表示帧指针的使用情况。我同意“如果计数很高”(例如,所有指令的千分之一,按顺序),则很有可能。对正则表达式的一次点击不一定是结论性的。 (2认同)