簡體   English   中英

處理器如何知道斷點?

[英]How does the processor know the breakpoints?

讓我們考慮這個非常簡單的程序:

#include<stdio.h>

int main () 
{
    int num1=4, num2=5;
    printf("Welcome\n");
    printf("num1 + num2 = %d\n", num1+num2);
    return 0;
}

使用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

我知道CPU看到編譯器為它生成的匯編代碼,我不明白程序是如何在用戶設置的breakpoint處停止的? 為什么CPU不繼續運行程序? 這是怎么回事? 我的意思是,為什么在取指令后它會停止?

我有點困惑,是Code :: Blocks照顧這個或用戶正在使用的程序嗎?

提前致謝!

大多數現代指令集都包含breakpoint異常,用於允許調試器通過使用特殊軟件中斷指令臨時替換相關程序指令,在程序代碼中插入斷點。 在x86 / x86-64 ISA上,該指令是“中斷向量3”(也就是int3 ),它通常作為單字節指令0xcc發出。

關於斷點指令的一個重要注意事項是它們通常必須至少與ISA上最小的可能指令一樣小。 這有幾個原因。 一些ISA需要最少的指令對齊; 較短的指令通常具有較不嚴格的對齊要求。 此外,用較長的指令替換某些指令意味着您可能會覆蓋以后的指令。 這在單線程應用程序中可能不是什么大問題,但在多線程應用程序中,它是一個顯示阻塞。 例如,考慮如果在可選分支的末尾用較長的指令替換短指令而另一個正在運行的線程跳過該分支可能會發生什么。

在其他情況下,可能不存在這樣的特殊指令。 在缺少特定斷點指令的硬件平台上,有時會提供特殊的硬件寄存器,以使處理器在嘗試訪問存儲器中的特定位置時進行陷阱。 這些寄存器的數量通常相當有限,因此在使用多個斷點進行調試時,專用斷點指令非常有用。

當您在調試器中啟動程序並添加啟用軟件的斷點時,通常會發生以下情況:

調試器將程序加載到內存中並為您提供一些輸入提示。 您告訴調試器添加斷點。 它可能會使用一些信息來確定內存中斷點實際上與程序的內存中表示形式相對應的位置。 然后,調試器對該地址處的指令進行解碼(因為它通常要替換整個指令)並用斷點指令替換它(在內存中)。 然后告訴調試器執行/繼續執行程序。

當處理器遇到此指令時,它會生成陷阱。 此陷阱作為中斷傳遞給操作系統,該操作系統注意到陷阱用於調試程序。 操作系統知道正在執行哪個程序(因此也正在執行它) - 因此它可以進行一些權限檢查,以確保此時實際上允許用戶調試應用程序。 如果一切看起來都很好,操作系統會通知調試器遇到斷點,並告訴您它已停止。

這不是一個普遍的解釋。 要實現上述要求,需要大量的OS支持。 在Linux和BSD上,大多數此功能是通過ptrace(2)系統調用公開的(它允許讀取和替換指令,以及單步執行)。 在符合POSIX標准的情況下,OS X不實現ptrace(2) ,而是為此提供各種Mach端口。 Windows完全有其他功能。

在嵌入式系統上,可能會提供特殊硬件端口(如JTAG )以允許在硬件級別進行內省,從而允許開發外部調試器,該調試器使用JTAG直接與硬件“對話”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM