日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CPU和软件模拟异常的执行流程

發布時間:2025/3/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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異常的處理流程

  • CPU指令檢測到異常,例如除零
  • 查IDT表(如下表),執行中斷處理函數
  • CommonDispatchException
  • KiDispatchException
  • 以除零異常為例,在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異常的執行流程:

  • CPU指令檢測到異常
  • 查IDT表,執行中斷處理函數
  • 調用CommonDispatchException,構建EXCEPTION_RECORD結構體
  • 調用KiDispatchException函數分發異常,目的是為了找到異常處理函數
  • 模擬異常記錄

    模擬異常的執行流程

    示例代碼如下:

    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函數分析

    這個函數主要做了兩件事

  • 把EXCEPTION_RECORD結構體的ExceptionCode最高位清零,用于區分CPU異常
  • 調用KiDispatchException開始分發異常
  • 總結

    總結

    以上是生活随笔為你收集整理的CPU和软件模拟异常的执行流程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。