2010-12-03 60 views
5

我正在Delphi的Xbox1模擬器上工作,因爲我在本地CPU上運行遊戲,所以我必須爲遊戲代碼內部可能發生的ring0指令創建故障安全。SetUnhandledExceptionFilter:繼續執行1操作碼進一步

爲了能夠捕獲這些指令,我已經瞭解到SetUnhandledExceptionFilter可以註冊一個函數,該函數將在非Delphi異常時調用(假設我將JITEnable設置爲大於0的值)。在註冊的回調函數的簽名寫着:

function ExceptionFilter(E: LPEXCEPTION_POINTERS): Integer; stdcall; 

內部的功能,我可以測試非法指令是這樣的:

// STATUS_PRIVILEGED_INSTRUCTION = $C0000096 
if E.ExceptionRecord.ExceptionCode = STATUS_PRIVILEGED_INSTRUCTION then 

之一違規指令是WVINDB($ 0F,$ 09),其我可以檢測到這樣的:

// See if the instruction pointer is a WBINVD opcode : 
if (PAnsiChar(E.ExceptionRecord.ExceptionAddress)[0] = #$0F) 
and (PAnsiChar(E.ExceptionRecord.ExceptionAddress)[1] = #$09) then 

這一切工作(我提供運行該調試器),但我不能讓代碼執行超出失敗的指令 - 我試過這樣的:

begin 
    // Skip the WBINVD instruction, and continue execution : 
    Inc(DWORD(E.ExceptionRecord.ExceptionAddress), 2); 
    Result := EXCEPTION_CONTINUE_EXECUTION; 
    Exit; 
    end; 

唉,這是行不通的。實際上,我會使用真正的指令指針(E.ContextRecord.Eip),但不知怎的,整個ContextRecord似乎並沒有被填充。

我能做些什麼確實按預期工作嗎? PS:當用調試器運行時,我希望這段代碼最終在我的ExceptionFilter例程中,但它不會 - 它只能在沒有調試器的情況下工作;爲什麼?

DebugHook := 0; // Act as if there's no debugger 
// Trigger a privileged instruction exception via this ring0 instruction : 
asm 
    WBINVD 
end; 
// Prove that my exception-filter worked : 
ShowMessage('WBINVD succesfully ignored!'); 

回答

3

SetUnhandledExceptionFilter似乎是某種Delphi包裝器,如果你直接做,你可能會有更多的運氣?

您可以註冊您自己的異常處理程序AddVectoredExceptionHandler,這將調用callback函數,該函數爲您提供EXCEPTION_POINTERS結構。該結構的Context成員返回可以修改的EIP。

如果您在給定的EIP處繼續回調執行中返回EXCEPTION_CONTINUE_EXECUTION。

+1

此外,SetUnhandledExceptionFilter是一個內核API:http://msdn.microsoft.com/en-us/library/ms680634(VS.85).aspx – PatrickvL 2010-12-04 12:02:16