軟件調試之INT 3講解


第4章斷點和單步執行

斷點和單步執行是兩個經常使用的調試功能,也是調試器的核心功能。本章我們將介紹IA-32 CPU是如何支持斷點和單步執行功能的。前兩節將分別介紹軟件斷點和硬件斷點,第4.3節介紹用於實現單步執行功能的陷阱標志。在前三節的基礎上,第 4.4節將分析一個真實的調試器程序,看它是如何實現斷點和單步執行功能的。

4.1  軟件斷點

x86系列處理器從其第一代產品英特爾8086開始就提供了一條專門用來支持調試的指令,即INT 3。簡單地說,這條指令的目的就是使CPU中斷(break)到調試器,以供調試者對執行現場進行各種分析。當我們調試程序時,可以在可能有問題的地方插 入一條INT 3指令,使CPU執行到這一點時停下來。這便是軟件調試中經常用到的斷點(breakpoint)功能,因此INT 3指令又被稱為斷點指令。

4.1.1  感受INT 3

下面通過一個小實驗來感受一下INT 3指令的工作原理。在Visual C++ Studio 6.0(以下簡稱為VC6)中創建一個簡單的HelloWorld控制台程序HiInt3,然后在main()函數的開頭通過嵌入式匯編插入一條INT 3指令:

int main(INT argc, char* argv[])
{
// manual breakpoint
_asm INT 3;
printf("Hello INT 3!\n");
return 0;
}

當在VC環境中執行以上程序時,會得到圖4-1所示的對話框。點OK按鈕后,程序便會停在INT 3指令所在的位置。由此看來,我們剛剛插入的一行(_asm INT 3)相當於在那里設置了一個斷點。實際上,這也正是通過注入代碼手工設置斷點的方法,這種方法在調試某些特殊的程序時還非常有用。

 
圖4-1  CPU遇到INT 3指令時會把執行權移交給調試器

此時打開反匯編窗口,可以看到內存地址00401028處確實是INT 3指令:

10:       _asm INT 3;
00401028   int         3

打開寄存器窗口,可以看到程序指針寄存器的值也是00401028。

EAX = CCCCCCCC EBX = 7FFDE000 ECX = 00000000 EDX = 00371588
ESI = 00000000 EDI = 0012FF80
EIP = 00401028 ESP = 0012FF34 EBP = 0012FF80 ……

根據我們在第3章中的介紹,斷點異常(INT 3)屬於陷阱類異常,當CPU產生異常時,其程序指針是指向導致異常的下一條指令的。但是,現在我們觀察到的結果卻是指向導致異常的這條指令的。這是為什 么呢?簡單地說,是操作系統為了支持調試對程序指針做了調整。我們將在后面揭曉答案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM