SetUnhandledExceptionFilter:继续执行1操作码

时间:2010-12-03 19:58:22

标签: delphi exception-handling

我正在使用Delphi中的Xbox1模拟器,因为我在本地CPU上运行游戏,我必须为游戏代码中可能出现的ring0指令创建故障保护。

为了能够捕获这些指令,我了解到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!');

1 个答案:

答案 0 :(得分:3)

SetUnhandledExceptionFilter似乎是某种Delphi封装器,如果你直接这样做,也许你有更多的运气?

您可以使用AddVectoredExceptionHandler注册自己的异常处理程序,这将调用callback函数,该函数为您提供EXCEPTION_POINTERS结构。该结构的Context成员返回ao EIP,您可以修改它。

如果在回调执行中返回EXCEPTION_CONTINUE_EXECUTION,则继续执行给定的EIP。