CPU和软件模拟异常的执行流程
文章目錄
- CPU異常記錄
- 異常的分類
- CPU產生的異常
- 軟件模擬產生的異常
- CPU異常的處理流程
- CommonDispatchException函數分析
- 總結
- 模擬異常記錄
- 模擬異常的執行流程
- RaiseException函數分析
- KiRaiseException函數分析
- 總結
異常產生后,首先要記錄異常信息(異常的類型 異常發生的位置等),然后要尋找異常的處理函數,我們稱為異常分發,最后找到異常處理函數并調用,我們稱為異常處理
CPU異常記錄
異常的分類
CPU產生的異常
例如下面的代碼:
void Test() {int x = 10;int y = 0;int z = x/y; }當代碼執行時,CPU檢測到除數為零,這個時候就CPU就會拋出異常
軟件模擬產生的異常
在C++或者是C#等一些高級語言中,在程序需要的時候也可以主動拋出異常,這種高級語言拋出的異常就是模擬產生的異常,并不是真正的異常。
CPU異常的處理流程
以除零異常為例,在Windows內核文件中分析一下整體的流程,打開ntkrnlpa.idb
首先按Alt+T鍵搜索_IDT,找到中斷處理函數表。
其中_KiTrap00就是除零異常對應的處理函數
首先,異常處理函數會保存當前的寄存器環境到TrapFrame,也就是零環的堆棧
接著,異常處理函數并沒有直接處理異常,而是調用了CommonDispatchException函數。
CommonDispatchException內部又調用了_KiDispatchException。CPU這么設計的目的是為了讓程序員有機會對異常進行處理。
CommonDispatchException函數分析
CommonDispatchException主要就做了一件事情,就是將異常相關的信息存儲到一個_EXCEPTION_RECORD結構體里,這個結構體的作用就是用來記錄異常信息
type struct _EXCEPTION_RECORD { DWORD ExceptionCode; //異常代碼DWORD ExceptionFlags; //異常狀態struct _EXCEPTION_RECORD* ExceptionRecord; //下一個異常PVOID ExceptionAddress; //異常發生地址DWORD NumberParameters; //附加參數個數ULONG_PTR ExceptionInformation [EXCEPTION_MAXIMUM_PARAMETERS]; //附加參數指針 }首先來解釋一下異常代碼和異常發生時的地址,回到CommonDispatchException函數調用之前
.text:004663F7 sti .text:004663F8 mov ebx, [ebp+68h] ; 發生異常時的EIP .text:004663FB mov eax, 0C0000094h ; 異常代碼 .text:00466400 jmp loc_4661E3 ; 跳轉到CommonDispatchException這里傳遞了兩個參數,一個是發生異常時的EIP,另一個是異常代碼,這個是CPU自己在內部定義的,除零異常對應的異常代碼就是0C0000094。如下圖
接著來解釋一下ExceptionFlags異常狀態,通過異常狀態可以區分是CPU產生的異常還是軟件模擬產生的異常。所有的CPU產生的異常這個位置的值是0,所有軟件模擬產生的異常這個位置存儲的值是1,如果堆棧錯誤里面存儲的值是8,如果出現嵌套異常,里面存儲的值是0x10。
總結
CPU異常的執行流程:
模擬異常記錄
模擬異常的執行流程
示例代碼如下:
void Test() {throw 1; }當通過軟件拋出異常的時候,實際上就是調用了CxxThrowException。
CxxThrowException會調用Kernel32.dll里的RaiseException
RaiseException會調用ntdlld.dll里的RtlRaiseException函數。
而這個函數繼續往下會調用NtRaiseException和KiRaiseException,最后調用KiDispatchException
RaiseException函數分析
用IDA打開kernel32.dll,找到RaiseException函數
這個函數要做的事情也很簡單,就是在堆棧里構建一個EXCEPTION_RECORD結構體,然后對結構體進行賦值。
CPU產生的異常也是要填充這樣一個結構體,兩者之間有一些不同之處。
ExceptionCode 異常代碼
首先是ExceptionCode的差異,CPU異常每種不同類型的異常都對應一個具體的32位的值,但是軟件模擬的異常和當前的編譯環境有關。
ExceptionAddress 異常發生地址
第二個區別就是ExceptionAddress,CPU異常記錄的位置是真正的異常發生時的地址
軟件模擬產生的異常里面存儲的是RaiseException這個函數的地址。
KiRaiseException函數分析
這個函數主要做了兩件事
總結
總結
以上是生活随笔為你收集整理的CPU和软件模拟异常的执行流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: APC机制详解
- 下一篇: 用户层和内核层异常的处理流程