Delphi SetUnhandledExceptionFilter:继续执行1操作码

Delphi SetUnhandledExceptionFilter:继续执行1操作码,delphi,exception-handling,Delphi,Exception Handling,我正在用Delphi开发Xbox1模拟器,因为我在本地CPU上运行游戏,所以我必须为游戏代码中可能出现的ring0指令创建故障保护 为了能够捕获这些指令,我了解到SetUnhandledExceptionFilter可以注册一个函数,该函数将在非Delphi异常时被调用(前提是我将JITEnable设置为大于0的值)。已注册回调函数的签名如下: function ExceptionFilter(E: LPEXCEPTION_POINTERS): Integer; stdcall; 在该函数中,

我正在用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
 // See if the instruction pointer is a WBINVD opcode :
 if  (PAnsiChar(E.ExceptionRecord.ExceptionAddress)[0] = #$0F)
 and (PAnsiChar(E.ExceptionRecord.ExceptionAddress)[1] = #$09) then
其中一个违规指令是WVINDB($0F,$09),我可以通过以下方式检测到:

// STATUS_PRIVILEGED_INSTRUCTION = $C0000096
if E.ExceptionRecord.ExceptionCode = STATUS_PRIVILEGED_INSTRUCTION then
 // 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似乎是某种Delphi包装器,如果直接使用它,可能会更幸运

您可以向注册自己的异常处理程序,这将调用一个函数,为您提供一个结构。该结构的上下文成员返回可以修改的ao EIP


如果返回EXCEPTION\u CONTINUE\u,则回调中的执行将在给定的EIP上继续。

此外,SetUnhandledExceptionFilter是一个内核API:哦,阅读文档,您对上下文成员的看法似乎是正确的,但正如我前面所说,它没有填充!只有ExceptionRecord看起来是正常的-ContextRecord看起来未初始化。@PatrickvL:它适用于XP及更高版本(请参阅MSDN)。关于SetUnhandledExceptionFilter,MSDN文档说:指向顶级异常筛选函数的指针,每当UnhandledExceptionFilter函数获得控制时,将调用该函数,并且进程未被调试。AddVectoredExceptionHandler在调试器中工作,请尝试一下!AddVectoredExceptionHandler他?我试试看。它似乎从WinXP开始就可用,这很好。(之前,我将其与AddVectoredContinueHandler混合使用,后者仅在Vista之后可用)。