2015-02-24 94 views
2

我正在開發玩具CPU(TR3200 cpu)的仿真器。其實我有一個純粹的解釋器核心,但我正在研究開發一個追蹤JIT cpu核心。 我對如何追蹤被追蹤的源機器代碼是否被仿真代碼修改(自修改代碼或類似將操作系統加載到RAM的操作系統) 我在考慮使用段或間隔爲此,但我找不到任何信息或實例如何處理。JIT仿真和跟蹤髒內存塊

換句話說......我知道JIT(我在考慮如何使用asmjit),我應該在使用jitted塊的開始地址作爲索引的地圖上存儲jitted代碼;我有一些想法如何處理循環計數和設備與jitted代碼同步。但是當guest程序寫入一個jitted內存塊時,我不清楚如何處理。

例如:我們有一個簡單的操作系統,它在地址0x100-0x500處執行了一個程序,並且它正確返回。 JIT cpu核心會(樂觀地)生成代表這些代碼塊的本地機器代碼。現在,如果操作系統加載另一個程序並將其放置在0x200-0x300地址塊上,則不應使覆蓋後的0x100-0x500的舊jitted塊失效。 或者是最糟糕的情況,一個自我重寫的程序,會導致jitted塊無效。 如何檢測?

+1

嘿!爲什麼要投票? – Zardoz89 2015-02-24 16:53:28

+0

可能因爲沒有明確的問題。 :-) – 2015-02-24 19:35:51

+0

謝謝你爲什麼反對投票的答案。我會嘗試重寫。我在一天的漫長的一天之前在醫院的一間候診室裏用電話寫了一封...... – Zardoz89 2015-02-24 19:43:36

回答

3

即使使用適度複雜的數據結構來跟蹤訪客內存更改的問題是,它必須能夠從jitted代碼中查詢和更新它。爲了避免代碼大小的荒謬性,您可能需要在調用代碼執行存儲指令時插入對某個寫入間隔樹的函數的調用(而不是內聯)。性能很可能會受到影響,您可能已經將代碼解釋爲開頭。此外,必須格外小心,以免模擬器的其他部分在不更新數據結構的情況下寫入相應的頁面。

有一個稍微不便攜的方法,涉及利用主機操作系統的虛擬內存設施。當您的JIT爲一大塊訪客內存發出代碼時,將相應的虛擬內存頁面標記爲只讀。任何後續寫入嘗試都會觸發可由您的主機程序捕獲的異常(例如SIGSEGV)。收到此異常後,您的主機程序會立即使從客戶內存中生成的與錯誤頁面重疊的所有jitter代碼無效,然後重新啓用對該頁面的寫入訪問權限,以便商店可以完成。

雖然此解決方案可以應付大多數寫入,但它並不處理一段跳動代碼修改緊隨其後的指令的情況。爲了明白爲什麼,考慮會發生什麼:

  1. jitted代碼存儲到guest虛擬機內存的一部分,從這個guest虛擬機內存中緊接着一條指令被激發。
  2. 主機程序引發並處理異常。來自錯誤頁面的所有跳轉代碼(包括商店首先觸發異常的代碼)都會失效。寫訪問再次啓用。
  3. 異常處理程序返回,但在哪裏?爲什麼,對於錯誤的指令,當然是,這是失效代碼的一部分!呃 - 哦!

據我所知,有兩種選擇。要麼忽略這個問題,要麼有效地使修改其附近的指令的代碼行爲未定義,要麼在異常處理程序中設置某種無效標誌,並在每個存儲區之後對其進行測試,如果測試失敗,則釋放到解釋器中。

快速搜索建議QEMU might be using a similar mechanism來處理來賓存儲器的修改,但我無法驗證它。