我正在学习 gdb 中的 int 3 指令和断点。 但我发现了一些奇怪的事情。 我的c代码如下:
#include<stdio.h>
int main(int argc, char *argv[]) {
int a = 4;
a += 3;
int b = 4;
int c = b*a;
printf("%d\n", c);
return 0;
}
然后编译:
gcc ./test.c
然后使用gdb,输出如下:
[xxx@xxxx 23:29:23 ~]
$ gdb ./a.out
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...
(No debugging symbols found in ./a.out)
(gdb) run
Starting program: /home/heyuanhong/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
28
[Inferior 1 (process 179733) exited normally]
(gdb) disassemble main
Dump of assembler code for function main:
0x0000555555555149 <+0>: endbr64
0x000055555555514d <+4>: push %rbp
0x000055555555514e <+5>: mov %rsp,%rbp
0x0000555555555151 <+8>: sub $0x20,%rsp
0x0000555555555155 <+12>: mov %edi,-0x14(%rbp)
0x0000555555555158 <+15>: mov %rsi,-0x20(%rbp)
0x000055555555515c <+19>: movl $0x4,-0xc(%rbp)
0x0000555555555163 <+26>: addl $0x3,-0xc(%rbp)
0x0000555555555167 <+30>: movl $0x4,-0x8(%rbp)
0x000055555555516e <+37>: mov -0x8(%rbp),%eax
0x0000555555555171 <+40>: imul -0xc(%rbp),%eax
0x0000555555555175 <+44>: mov %eax,-0x4(%rbp)
0x0000555555555178 <+47>: mov -0x4(%rbp),%eax
0x000055555555517b <+50>: mov %eax,%esi
0x000055555555517d <+52>: lea 0xe80(%rip),%rax # 0x555555556004
0x0000555555555184 <+59>: mov %rax,%rdi
0x0000555555555187 <+62>: mov $0x0,%eax
0x000055555555518c <+67>: call 0x555555555050 <printf@plt>
0x0000555555555191 <+72>: mov $0x0,%eax
0x0000555555555196 <+77>: leave
0x0000555555555197 <+78>: ret
End of assembler dump.
(gdb) b *0x0000555555555171
Breakpoint 1 at 0x555555555171
(gdb) x/1bx 0x0000555555555171
0x555555555171 <main+40>: 0x0f
(gdb) disassemble main
Dump of assembler code for function main:
0x0000555555555149 <+0>: endbr64
0x000055555555514d <+4>: push %rbp
0x000055555555514e <+5>: mov %rsp,%rbp
0x0000555555555151 <+8>: sub $0x20,%rsp
0x0000555555555155 <+12>: mov %edi,-0x14(%rbp)
0x0000555555555158 <+15>: mov %rsi,-0x20(%rbp)
0x000055555555515c <+19>: movl $0x4,-0xc(%rbp)
0x0000555555555163 <+26>: addl $0x3,-0xc(%rbp)
0x0000555555555167 <+30>: movl $0x4,-0x8(%rbp)
0x000055555555516e <+37>: mov -0x8(%rbp),%eax
0x0000555555555171 <+40>: imul -0xc(%rbp),%eax
0x0000555555555175 <+44>: mov %eax,-0x4(%rbp)
0x0000555555555178 <+47>: mov -0x4(%rbp),%eax
0x000055555555517b <+50>: mov %eax,%esi
0x000055555555517d <+52>: lea 0xe80(%rip),%rax # 0x555555556004
0x0000555555555184 <+59>: mov %rax,%rdi
0x0000555555555187 <+62>: mov $0x0,%eax
0x000055555555518c <+67>: call 0x555555555050 <printf@plt>
0x0000555555555191 <+72>: mov $0x0,%eax
0x0000555555555196 <+77>: leave
0x0000555555555197 <+78>: ret
End of assembler dump.
首先,我在主函数中打印汇编代码,然后在地址中设置断点
0x0000555555555171
。之后我尝试打印 0x0000555555555171
的值,然后再次打印汇编代码。
我的问题是为什么在地址
0x0000555555555171
(imul -0xc(%rbp),%eax)中创建断点后,int 3
(操作码是0xcc
)指令不显示?
我认为地址
0x0000555555555171
应该是0xcc
,因为我只是set断点,并没有hit断点。
我的操作系统是ubuntu 22.04,gcc版本是11.4.0,CPU是Intel(R) Core(TM) i9-14900KF
总结其他人在评论中的回答:
0xCC
指令的int3
操作码覆盖程序文本set breakpoint always-inserted on
(默认为 off
)控制的。disas
假装它们不存在,因为通常你想看到原始的反汇编,而不是你会得到的被破坏的图片,其中原始反汇编被随机覆盖 0xCC
操作码(使被覆盖的指令的其余部分变得毫无意义或只是错误的)。disas
检查该缓冲区中的指令,您将看到 actual 指令,其中散布着 int3
操作码。