SetUnhandledExceptionFilter: Продолжить выполнение еще одного кода операции

Я работаю над эмулятором Xbox1 в Delphi, и, поскольку я запускаю игры на локальном процессоре, мне нужно создать отказоустойчивую систему для инструкций 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!');
5
задан PatrickvL 3 December 2010 в 19:58
поделиться