確定性全二進位翻譯:超越啟發式方法

Binary translation——將可執行檔從一種指令集架構 (ISA) 轉換到另一種的過程——長期以來一直是效能與正確性之間的拉鋸戰。傳統上,開發者必須在即時編譯 (JIT) 與靜態翻譯之間做選擇,即時編譯提供高效能,但會帶來執行時開銷與安全風險;而靜態翻譯則常依賴啟發式方法來猜測程式碼的起始與結束,導致在面對複雜二進位檔時可能失敗。

一個新的研究專案 Elevator 提出此範式的轉變。透過實作一種確定性、完全靜態的全二進位翻譯方法,徹底拋棄啟發式,Elevator 旨在提供靜態翻譯器通常缺乏的正確性保證。此方法對受規範的產業與高安全性環境具有重大意義,然而也會帶來二進位大小的高昂代價。

核心創新:超集合控制流程圖

大多數靜態翻譯器都在「反組譯問題」上掙扎:即在二進位資料塊中區分程式碼與資料的困難。當翻譯器遇到間接跳躍或看似程式碼的資料表時,通常會使用啟發式方法猜測最可能的路徑。若猜測錯誤,翻譯就會失敗。

Elevator 透過採用暴力且確定性的方式解決此問題。它不再猜測,而是考慮二進位中 每個位元組的所有可能詮釋。對每一個可行的詮釋產生獨立的翻譯,實質上建立了一個「超集合」控制流程圖 (CFG)。系統僅會剪除導致異常終止的路徑,確保原始二進位中任何有效的執行路徑都在翻譯後的版本中得到呈現。

折衷:效能與膨脹

雖然確定性方法保證了正確性,但也帶來了顯著的開銷。社群對此專案的討論突顯了幾項關鍵的折衷:

1. 二進位大小爆炸

Elevator 方法最顯著的結果之一是 .text 區段大小的增加。翻譯後的二進位檔案可能比原始檔案大 50 倍

.text 區段大小增加 50 倍是巨大的,但對於完全確定性的翻譯而言,這似乎是一個合理的代價。相較於模擬的效能差異在許多情況下會超過大小增加所帶來的不便。

然而,其他批評者認為此程度的膨脹是「快取災難」,暗示二進位大小的增加可能因指令快取未命中而抵消避免 JIT 開銷所帶來的效能提升。

2. 執行速度

Elevator 相較於傳統模擬(如 QEMU)可提升約 4.75 倍 的執行速度,但仍慢於像 Apple 的 Rosetta 2 或 Box64 等高度最佳化的 JIT 解決方案。速度的提升是以 執行指令數增加 7 倍 為代價,因為翻譯器必須管理模擬的 x86 CPU 狀態(例如 EFLAGS)並逐一處理複雜的移動操作。

實務影響與限制

儘管有理論上的突破,Elevator 目前仍有多項限制,使其尚未成為通用工具:

  • 僅單執行緒: 仍未支援多執行緒或例外處理/解開。
  • ISA 覆蓋範圍: 不支援完整的 x86 ISA。
  • ABI 模擬: 它會模擬 x86 ABI,直到呼叫外部函式庫為止。

認證解鎖

或許此技術最有價值的應用並非一般消費者軟體,而是受規範產業。在航空或醫療器材等領域,JIT 編譯常被禁止,因為執行的程式碼必須與已認證、簽署的程式碼完全相同。

受規範的產業(航空、醫療器材)正因為此原因無法使用 JIT,執行的程式碼必須是已認證的程式碼。能產生可簽署二進位的靜態翻譯在此是真正的解鎖。

透過產生確定性的靜態、可簽署二進位,Elevator 為舊有 x86 程式碼在不允許執行時產生程式碼的安全或規範環境中移植至新架構提供了一條道路。

理論挑戰:Rice 定理

技術批評者指出,儘管 Elevator 的方法令人印象深刻,但它無法「解決」計算的根本限制。Rice 定理指出,任何非平凡的程式屬性都是不可判定的。具體而言,自我修改程式碼或對抗性二進位(資料刻意偽裝成程式碼)的問題仍是一大挑戰。

正如貢獻者所指出,靜態翻譯在假設「合作二進位」——即由標準編譯器產生,而非手寫組合語言或為阻礙分析而設計的混淆程式碼——時最為有效。對於在執行時自行修改指令的二進位,完全靜態的方法必然會面臨根本性的障礙。

Sources