2010-12-03 92 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