反汇编器 otool 和 objdump 输出可执行文件中包含的确切机器指令吗?

问题描述 投票:0回答:1

我在名为 test.c 的文件中有这个简单的 C 程序:

void fx2(){

    int c = 30;
    c++;
}

void fx1(){

    int b = 20;
    b++;
    fx2();

}

int main(){

    int a = 10;
    a++; 
    fx1();
}

我使用“gcc test.c -o test”在 Ubuntu (22.04.3) x86_64 系统中编译了这个。 然后我使用“objdump -d test”,得到了这个:

0000000000001129 <fx2>:
    1129:   f3 0f 1e fa             endbr64 
    112d:   55                      push   %rbp
    112e:   48 89 e5                mov    %rsp,%rbp
    1131:   c7 45 fc 1e 00 00 00    movl   $0x1e,-0x4(%rbp)
    1138:   83 45 fc 01             addl   $0x1,-0x4(%rbp)
    113c:   90                      nop
    113d:   5d                      pop    %rbp
    113e:   c3                      ret    

000000000000113f <fx1>:
    113f:   f3 0f 1e fa             endbr64 
    1143:   55                      push   %rbp
    1144:   48 89 e5                mov    %rsp,%rbp
    1147:   48 83 ec 10             sub    $0x10,%rsp
    114b:   c7 45 fc 14 00 00 00    movl   $0x14,-0x4(%rbp)
    1152:   83 45 fc 01             addl   $0x1,-0x4(%rbp)
    1156:   b8 00 00 00 00          mov    $0x0,%eax
    115b:   e8 c9 ff ff ff          call   1129 <fx2>
    1160:   90                      nop
    1161:   c9                      leave  
    1162:   c3                      ret    

0000000000001163 <main>:
    1163:   f3 0f 1e fa             endbr64 
    1167:   55                      push   %rbp
    1168:   48 89 e5                mov    %rsp,%rbp
    116b:   48 83 ec 10             sub    $0x10,%rsp
    116f:   c7 45 fc 0a 00 00 00    movl   $0xa,-0x4(%rbp)
    1176:   83 45 fc 01             addl   $0x1,-0x4(%rbp)
    117a:   b8 00 00 00 00          mov    $0x0,%eax
    117f:   e8 bb ff ff ff          call   113f <fx1>
    1184:   b8 00 00 00 00          mov    $0x0,%eax
    1189:   c9                      leave  
    118a:   c3                      ret    

我还在 macOS (Monteray 12.6.5) x86_64 系统中使用“clang test.c -o test”编译了 test.c。然后我使用“otool -tV test”,得到了这个:

(__TEXT,__text) section
_fx2:
0000000100003f40    pushq   %rbp
0000000100003f41    movq    %rsp, %rbp
0000000100003f44    movl    $0x1e, -0x4(%rbp)
0000000100003f4b    movl    -0x4(%rbp), %eax
0000000100003f4e    addl    $0x1, %eax
0000000100003f51    movl    %eax, -0x4(%rbp)
0000000100003f54    popq    %rbp
0000000100003f55    retq
0000000100003f56    nopw    %cs:(%rax,%rax)
_fx1:
0000000100003f60    pushq   %rbp
0000000100003f61    movq    %rsp, %rbp
0000000100003f64    subq    $0x10, %rsp
0000000100003f68    movl    $0x14, -0x4(%rbp)
0000000100003f6f    movl    -0x4(%rbp), %eax
0000000100003f72    addl    $0x1, %eax
0000000100003f75    movl    %eax, -0x4(%rbp)
0000000100003f78    callq   _fx2
0000000100003f7d    addq    $0x10, %rsp
0000000100003f81    popq    %rbp
0000000100003f82    retq
0000000100003f83    nopw    %cs:(%rax,%rax)
0000000100003f8d    nopl    (%rax)
_main:
0000000100003f90    pushq   %rbp
0000000100003f91    movq    %rsp, %rbp
0000000100003f94    subq    $0x10, %rsp
0000000100003f98    movl    $0xa, -0x4(%rbp)
0000000100003f9f    movl    -0x4(%rbp), %eax
0000000100003fa2    addl    $0x1, %eax
0000000100003fa5    movl    %eax, -0x4(%rbp)
0000000100003fa8    callq   _fx1
0000000100003fad    xorl    %eax, %eax
0000000100003faf    addq    $0x10, %rsp
0000000100003fb3    popq    %rbp
0000000100003fb4    retq

这是我的问题:

  1. 考虑到这个简单的 C 程序,我可以 100% 确定 otool 和 objdump 显示可执行测试中包含的确切机器指令吗?例如,两个函数序言指令 Pushq %rbp 和 movq %rsp,%rbp" 是否真正包含在实际的可执行“测试”中,或者这些反汇编器可以省略/添加/修改指令以使程序更易于阅读和遵循?

  2. 看起来 Ubuntu 和 macOS 中的 gcc 和 clang 分别使用了帧指针。我们是否可以说 Ubuntu 和 macOS 系统确实使用了帧指针,或者更合适的说法是只有 Ubuntu 和 macOS 上下文中的特定编译器 gcc 和 clang 分别使用了帧指针?

c assembly x86-64 objdump otool
1个回答
0
投票
  1. 反汇编程序通常会准确地发出可执行文件中的指令。他们可能会遇到一些麻烦,因为二进制数据以一种不会混淆处理器的方式散布在指令中,但可能使反汇编器很难决定代码在哪里继续。例如,clang 编译器似乎生成“无意义”字节作为填充,以便下一个函数在 16 字节边界上启动,这对缓存行为有好处。反汇编程序不知道这一点,并尝试将它们解释为指令。
  2. 使用帧指针(以及哪些寄存器用于参数和返回值传递)是 ABI 或调用约定的一部分,该约定通常针对平台(操作系统)给出,并由该平台的编译器遵循。某些语言可能在内部使用不同的调用约定,但在与 C 库代码交互时使用标准平台约定。
© www.soinside.com 2019 - 2024. All rights reserved.