我正在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!');
此外,SetUnhandledExceptionFilter是一個內核API:http://msdn.microsoft.com/en-us/library/ms680634(VS.85).aspx – PatrickvL 2010-12-04 12:02:16