共用方式為


回溯程序

回溯程式碼陣列會以遞減順序排序。 發生例外狀況 (Exception) 時,作業系統會在內容記錄中儲存完整的內容。 接著會叫用例外狀況分派邏輯,而這會重複地執行下列步驟,尋找例外處理常式 (Exception Handler)。

  1. 使用儲存在內容記錄中目前的 RIP,搜尋描述目前函式的 RUNTIME_FUNCTION 表格項目 (如果是鏈結的 UNWIND_INFO 項目,則為函式的部分)。

  2. 如果找不到任何函式表項目,則表示位在分葉函式中,且 RSP 會直接指定返回指標。 位於 [RSP] 的返回指標會儲存在已更新的內容中,而模擬的 RSP 會遞增 8,並重複步驟 1。

  3. 如果找到函式表項目,則 RIP 可能會出現在三個區域中:a) 終解、b) 初構或 c) 由例外狀況處理常式所涵蓋的程式碼。

    • 狀況 a) 如果 RIP 在終解中,則控制項將離開函式,這個函式可能沒有與這個例外狀況關聯的例外處理常式,且終解的效用必須繼續,以計算呼叫端函式的內容。 為了判斷 RIP 是否在終解中,會檢查從 RIP 而來的程式碼資料流。 如果該程式碼資料流可符合合法終解的結尾部分,則 RIP 位在終解中,終解的剩餘部分會完成模擬,同時在每個指令處理後會更新內容記錄。 在這項操作完成後,會重複步驟 1。

    • 狀況 b) 如果 RIP 在初構中,則控制尚未進入函式,對於這個函式可能沒有與這個例外狀況關聯的例外處理常式,且初構的效用必須復原,以計算呼叫端函式的內容。 如果從函式起點到 RIP 的距離小於或等於回溯資訊中編碼的初構大小,則 RIP 位在初構中。 經由在回溯程式碼陣列中掃描,找出第一個位移小於或等於 RIP 從函式起點之位移的項目,然後復原回溯程式碼陣列中其餘項目的效用,初構的效用會完成回溯。 接著會重複步驟 1。

    • 狀況 c) 如果 RIP 不在初構或終解中,且函式有例外狀況處理常式 (UNW_FLAG_EHANDLER 已設定),則會呼叫語言特定處理常式。 處理常式會掃描其資料並視情況呼叫篩選函式。 語言特定處理常式可以傳回例外狀況已處理或要繼續搜尋。 處理常式也可以直接啟始回溯。

  4. 如果語言特定處理常式傳回已處理的狀態,則會繼續使用原始的內容記錄來執行。

  5. 如果沒有語言特定處理常式,或是處理常式傳回「繼續搜尋」狀態,則內容記錄必須回溯至呼叫端的狀態。 這項操作由處理所有回溯程式碼陣列元素,復原每一個元素的作用來完成。 接著會重複步驟 1。

當涉及鏈結的回溯資訊時,這些基本步驟還是會進行。 唯一不同的地方,是在逐一查看回溯程式碼陣列以回溯初構的作用時,一旦到達陣列結尾,就會連結至父回溯資訊,然後逐一查看在其中找到的整個回溯程式碼陣列。 這個連結動作會繼續,直到到達沒有 UNW_CHAINED_INFO 旗標的回溯資訊,並完成逐一查看其回溯程式碼陣列為止。

最小的回溯資料組是 8 位元組。 這表示只配置 128 位元組 (或更少) 堆疊的函式,並可能儲存一個靜態暫存器。 這也是不具回溯程式碼之零長度初構的鏈結回溯資訊結構的大小。

請參閱

參考

例外狀況處理 (x64)