正如标题所暗示的,有没有办法在机器代码指令被执行时/之后读取它们?例如,如果我有一个任意的 C 代码块,并且我想知道在输入该块时编译和执行了哪些指令,那么有没有办法做到这一点?提前感谢您提供有关该主题的任何指示。
编辑:关于我想要做什么的一些动机:我想要一个程序来粗略地弄清楚它是如何编译的或它当前正在运行什么指令,而实际上不需要知道机器代码是如何制作的。即我想使用一些编译器以前在编译程序时所做的艰苦工作,以便我可以复制并稍后使用正在执行的机器代码。
正如标题所暗示的,有没有办法在机器代码指令被执行时/之后读取它们?例如,如果我有一个任意的 C 代码块,并且我想知道在输入该块时编译和执行了哪些指令,那么有没有办法做到这一点?提前感谢您提供有关该主题的任何指示。
编辑:关于我想要做什么的一些动机:我想要一个程序来粗略地弄清楚它是如何编译的或它当前正在运行什么指令,而实际上不需要知道机器代码是如何制作的。即我想使用一些编译器以前在编译程序时所做的艰苦工作,以便我可以复制并稍后使用正在执行的机器代码。
鲜为人知的事实:GDB 有一个内置的 curses 接口。
Use gdbtui
or gdb
,Ctrl+X,Ctrl+A to enter, then Ctrl+X,2 to start showing assembly and source together. The current instruction is highlighted, and you can navigate using the arrow keys.
我不知道您是要在运行时执行此操作,还是要查看包含已编译 C 代码的汇编代码的文本文件。
如果是前者,只需使用调试器(使用 disassemble in gdb
withgcc
或 Microsoft Visual Studio 中的集成调试器)。
如果是后者,则必须查找编译器的特定命令。例如,使用 Visual Studio,只需使用标志/FAs
; 这将使用您的源代码输出汇编代码。对于gcc
:
gcc -c -g -Wa,-a,-ad foo.c > foo.lst
几乎每个调试器都可以做到这一点。
对于 gdb,需要记住的一个有用技巧是:display/i $pc
这样做一次,然后在函数上设置断点,使用stepi
and逐步执行函数nexti
。
每次都会自动显示PC端的指令。
Ross-Harveys-MacBook-Pro:so ross$ cat > deb.c
int main(void) { return (long)main + 0x123; }
Ross-Harveys-MacBook-Pro:so ross$ cc -O deb.c
Ross-Harveys-MacBook-Pro:so ross$ gdb -q a.out
Reading symbols for shared libraries .. done
(gdb) break main
Breakpoint 1 at 0x100000f30
(gdb) display/i $pc
(gdb) r
Starting program: /Users/ross/so/a.out
Reading symbols for shared libraries +. done
Breakpoint 1, 0x0000000100000f30 in main ()
1: x/i $pc 0x100000f30 <main+4>: lea -0xb(%rip),%rax # 0x100000f2c <main>
(gdb) stepi
0x0000000100000f37 in main ()
1: x/i $pc 0x100000f37 <main+11>: add $0x123,%eax
(gdb) stepi
0x0000000100000f3c in main ()
1: x/i $pc 0x100000f3c <main+16>: leaveq
大多数调试器都有选项来查看您正在执行的代码的反汇编。
例如:在 gdb 中使用 disassemble 命令。
如果您想知道特定功能的执行路径是什么,也许某些处理器具有这样的功能,但通常没有。现在您可以做的是在模拟器中运行并修改模拟器以打印出获取或读取的地址或其他任何内容。
如果这只是使用 gcc/binutils 工具 objdump -D 文件名 > out.list 的反汇编问题,而不是执行或使用调试器