Jam*_*234 9 c debugging assembly operating-system exception
让我们考虑这个非常简单的程序:
#include<stdio.h>
int main ()
{
int num1=4, num2=5;
printf("Welcome\n");
printf("num1 + num2 = %d\n", num1+num2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用以下方法查看生成的汇编代码时gcc -S prog.c:
.file "p.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "Welcome\0"
LC1:
.ascii "num1 + num2 = %d\12\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB10:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $4, 28(%esp)
movl $5, 24(%esp)
movl $LC0, (%esp)
call _puts
movl 28(%esp), %edx
movl 24(%esp), %eax
addl %edx, %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
call _getchar
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE10:
.ident "GCC: (GNU) 5.3.0"
.def _puts; .scl 2; .type 32; .endef
.def _printf; .scl 2; .type 32; .endef
.def _getchar; .scl 2; .type 32; .endef
Run Code Online (Sandbox Code Playgroud)
我知道CPU看到了编译器为它生成的汇编代码,我不明白的是程序是如何停止在breakpoint用户设置的?为什么CPU不继续运行程序?这是怎么回事?我的意思是,为什么在取指令后它会停止?
我有点困惑,是Code :: Blocks照顾这个或用户正在使用的程序吗?
提前致谢!
Ton*_*ous 11
大多数现代指令集都包含一个breakpoint异常,用于允许调试器通过使用特殊软件中断指令临时替换相关的程序指令,在程序代码中插入断点.在x86/x86-64 ISA上,该指令是"中断向量3"(又名int3),通常作为单字节指令发出0xcc.
关于断点指令的一个重要注意事项是它们通常必须至少与ISA上最小的可能指令一样小.这有几个原因.一些ISA需要最少的指令对齐; 较短的指令通常具有较不严格的对齐要求.此外,用较长的指令替换某些指令意味着您可能会覆盖以后的指令.这在单线程应用程序中可能不是什么大问题,但在多线程应用程序中,它是一个显示阻塞.例如,考虑如果在可选分支的末尾用较长的指令替换短指令而另一个正在运行的线程跳过该分支可能会发生什么.
在其他情况下,可能不存在这样的特殊指令.在缺少特定断点指令的硬件平台上,有时会提供特殊的硬件寄存器,以使处理器在尝试访问存储器中的特定位置时进行陷阱.这些寄存器的数量通常相当有限,因此在使用多个断点进行调试时,专用断点指令非常有用.
当您在调试器中启动程序并添加启用软件的断点时,通常会发生以下情况:
调试器将程序加载到内存中并为您提供一些输入提示.您告诉调试器添加断点.它可能会使用一些信息来确定内存中断点实际上与程序的内存中表示形式相对应的位置.然后,调试器对该地址处的指令进行解码(因为它通常要替换整个指令)并用断点指令替换它(在内存中).然后告诉调试器执行/继续执行程序.
当处理器遇到此指令时,它会生成陷阱.此陷阱作为中断传递给操作系统,该操作系统注意到陷阱用于调试程序.操作系统知道正在执行哪个程序(因此也正在执行它) - 因此它可以进行一些权限检查,以确保此时实际上允许用户调试应用程序.如果一切看起来都很好,操作系统会通知调试器遇到断点,并告诉您它已停止.
这不是一个普遍的解释.要实现上述要求,需要大量的OS支持.在Linux和BSD上,大多数此功能都是通过ptrace(2)syscall 公开的(它允许读取和替换指令,以及单步执行).虽然符合POSIX标准,但OS X并未实现ptrace(2),而是为此提供各种Mach端口.Windows完全有其他功能.
在嵌入式系统上,可能会提供特殊硬件端口(如JTAG)以允许在硬件级别进行内省,从而允许开发外部调试器,该调试器使用JTAG直接"说话"到硬件.
| 归档时间: |
|
| 查看次数: |
315 次 |
| 最近记录: |