otool与objdump指令准确性及栈帧指针使用的技术问询
C程序跨平台编译与反汇编分析
测试用C程序
void fx2(){ int c = 30; c++; } void fx1(){ int b = 20; b++; fx2(); } int main(){ int a = 10; a++; fx1(); }
Ubuntu 22.04.3 x86_64 编译与反汇编结果
使用命令gcc test.c -o test编译,再执行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 Monterey 12.6.5 x86_64 编译与反汇编结果
使用命令clang test.c -o test编译,再执行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. 反汇编工具是否展示可执行文件中的精确机器指令?
可以100%确认,默认情况下objdump和otool都是直接解析可执行文件中的二进制机器码,将其翻译成对应的汇编助记符,不会增删改任何指令。以函数序言的pushq %rbp为例,对应的机器码是0x55,在objdump的输出中能看到地址112d处的字节就是55,对应push %rbp;otool中地址0000000100003f40处的指令也是pushq %rbp,完全对应可执行文件中的二进制内容。只有当使用某些特殊选项(比如模拟优化后的指令展示)时,工具才可能做调整,但默认无选项的情况下,输出完全忠实于可执行文件中的机器指令。
2. 栈帧指针的使用应该归因于系统还是编译器?
准确的表述是特定环境下的GCC和Clang编译器使用栈帧指针,而非系统。栈帧指针的启用与否是编译器的编译选项控制的:比如GCC可以通过-fomit-frame-pointer选项禁用栈帧指针,Clang同样支持该选项;反之,即使在同一系统中,不同版本的编译器或不同的编译优化级别,也可能改变栈帧指针的使用策略。系统本身并不强制要求使用栈帧指针,这完全是编译器的选择。
内容的提问来源于stack exchange,提问作者alessio solari
相关产品推荐
相关产品推荐

