所以有"int 3"这是一个用于调试器断点的中断指令.
但是还有"int 1"用于单步执行.但为什么需要呢?我已经读过,在EFLAGS寄存器中设置陷阱标志(TF)将启用单步执行,并将为每条指令捕获到操作系统.那么为什么需要单独的中断类型呢?
谢谢!
我知道可执行文件中的软件断点可以通过用另一个替换所需位置的某些汇编指令来工作,这会导致中断.因此,调试器可以在此处完全停止执行,并将此指令替换为原始指令,并询问用户下一步操作或调用某些命令等.
但是这样的可执行文件的代码不被其他程序使用,并且在内存中只有一个副本.软件断点如何与共享库一起使用?例如,如果我在C库的某个内部函数中设置一个软件断点,它的工作原理(据我所知它只有一个副本用于所有应用程序,所以我们不能只替换它中的一些指令)?是否有为此目的的"软件断点"技术?
我在llvm clang Apple LLVM 8.0.0版(clang-800.0.42.1)上反汇编代码:
int main() {
float a=0.151234;
float b=0.2;
float c=a+b;
printf("%f", c);
}
Run Code Online (Sandbox Code Playgroud)
我编译时没有-O规范,但我也试过-O0(给出相同)和-O2(实际上计算值并存储它预先计算)
产生的反汇编如下(我删除了不相关的部分)
-> 0x100000f30 <+0>: pushq %rbp
0x100000f31 <+1>: movq %rsp, %rbp
0x100000f34 <+4>: subq $0x10, %rsp
0x100000f38 <+8>: leaq 0x6d(%rip), %rdi
0x100000f3f <+15>: movss 0x5d(%rip), %xmm0
0x100000f47 <+23>: movss 0x59(%rip), %xmm1
0x100000f4f <+31>: movss %xmm1, -0x4(%rbp)
0x100000f54 <+36>: movss %xmm0, -0x8(%rbp)
0x100000f59 <+41>: movss -0x4(%rbp), %xmm0
0x100000f5e <+46>: addss -0x8(%rbp), %xmm0
0x100000f63 <+51>: movss %xmm0, -0xc(%rbp)
...
Run Code Online (Sandbox Code Playgroud)
显然它正在做以下事情:
我已经读到 GDB 在目标程序内存中的所需地址处放置了一个 int 3(操作码 CC)。
Si 这个操作是擦除程序存储器中的一条指令(1 个字节)。我的问题是:当程序继续时,GDB 如何以及何时替换原始操作码?
当我在 GDB 中键入反汇编时,我看不到 CC 操作码。这是因为 GDB 知道是他放了 CC 吗?有没有办法进行原始反汇编,以便准确查看此时内存中加载了哪些操作码?
gdb ×3
debugging ×2
assembly ×1
breakpoints ×1
c ×1
internals ×1
llvm-codegen ×1
x86 ×1
x86-64 ×1