【发布时间】:2010-09-07 03:39:43
【问题描述】:
我知道我可以通过以下方式获得编译器生成的汇编器源代码:
gcc -S ...
尽管这很烦人并没有给我一个目标文件作为过程的一部分。
但是我怎样才能获得有关编译代码的所有信息?我的意思是地址、生成的字节等等。
gcc -S 输出的指令没有告诉我任何关于指令长度或编码的信息,这是我想看到的。
【问题讨论】:
我知道我可以通过以下方式获得编译器生成的汇编器源代码:
gcc -S ...
尽管这很烦人并没有给我一个目标文件作为过程的一部分。
但是我怎样才能获得有关编译代码的所有信息?我的意思是地址、生成的字节等等。
gcc -S 输出的指令没有告诉我任何关于指令长度或编码的信息,这是我想看到的。
【问题讨论】:
我喜欢 objdump 这一点,但最有用的选项并不明显 - 特别是如果您在包含重定位的目标文件上使用它,而不是最终的二进制文件。
objdump -d some_binary 做得很合理。
objdump -d some_object.o 用处不大,因为对外部函数的调用不会被反汇编:
...
00000005 <foo>:
5: 55 push %ebp
6: 89 e5 mov %esp,%ebp
8: 53 push %ebx
...
29: c7 04 24 00 00 00 00 movl $0x0,(%esp)
30: e8 fc ff ff ff call 31 <foo+0x2c>
35: 89 d8 mov %ebx,%eax
...
call 实际上是printf()...添加-r 标志有助于解决此问题;它标志着搬迁。 objdump -dr some_object.o 给:
...
29: c7 04 24 00 00 00 00 movl $0x0,(%esp)
2c: R_386_32 .rodata.str1.1
30: e8 fc ff ff ff call 31 <foo+0x2c>
31: R_386_PC32 printf
...
然后,我发现将每一行注释为<symbol+offset> 很有用。 objdump 有一个方便的选项,但它具有关闭实际字节转储的烦人副作用 - objdump --prefix-addresses -dr some_object.o 给出:
...
00000005 <foo> push %ebp
00000006 <foo+0x1> mov %esp,%ebp
00000008 <foo+0x3> push %ebx
...
但事实证明,您可以通过提供另一个模糊选项来撤消该操作,最终得到我最喜欢的objdump 咒语:
objdump --prefix-addresses --show-raw-insn -dr file.o
输出如下:
...
00000005 <foo> 55 push %ebp
00000006 <foo+0x1> 89 e5 mov %esp,%ebp
00000008 <foo+0x3> 53 push %ebx
...
00000029 <foo+0x24> c7 04 24 00 00 00 00 movl $0x0,(%esp)
2c: R_386_32 .rodata.str1.1
00000030 <foo+0x2b> e8 fc ff ff ff call 00000031 <foo+0x2c>
31: R_386_PC32 printf
00000035 <foo+0x30> 89 d8 mov %ebx,%eax
...
如果您使用调试符号构建(即使用-g 编译),并且将-dr 替换为-Srl,它将尝试使用相应的源代码行注释输出。
【讨论】:
获得快速列表的最简单方法是使用汇编程序的-a 选项,您可以通过在gcc 命令行上输入-Wa,-a 来实现。您可以对 a 选项使用各种修饰符来准确影响结果 - 请参阅 as(1) 手册页。
【讨论】:
听起来你想要一个反汇编程序。 objdump 几乎是标准的(otool 在 Mac OS X 上);与链接器为您提供的任何映射文件信息相一致,目标文件的反汇编应该为您提供所需的一切。
【讨论】:
gcc 将生成一个汇编语言源文件。然后,您可以使用as -a yourfile.S 生成一个列表,其中包括每条指令的偏移量和编码字节。 -a 也有一些子选项来控制列表文件中显示的内容(as --help 将提供它们的列表以及其他可用选项)。
【讨论】:
nasm -f elf xx.asm -l x.lst
gcc xx.c xx.o -o xx
生成一个“列表”文件 x.lst,它只用于 xx.asm
对于 xx.c 和 xx.asm,您可以同时编译它们,然后使用 'gdb' - gnu 调试器
【讨论】: