Estoy trabajando en un emulador de Xbox1 en Delphi, y como ejecuto los juegos en la CPU local, tengo que crear un failsafe para las instrucciones ring0 que pueden ocurrir dentro del código de juego.SetUnhandledExceptionFilter: Continuar ejecución 1 código de operación más
Para poder interceptar estas instrucciones, he descubierto que SetUnhandledExceptionFilter puede registrar una función que se invocará en excepciones que no sean de Delphi (siempre que establezca JITEnable en un valor superior a 0). La firma de la función de devolución de llamada registrada lee:
function ExceptionFilter(E: LPEXCEPTION_POINTERS): Integer; stdcall;
Dentro de esa función, que puede probar para ver las instrucciones ilegales como esto:
// STATUS_PRIVILEGED_INSTRUCTION = $C0000096
if E.ExceptionRecord.ExceptionCode = STATUS_PRIVILEGED_INSTRUCTION then
Una de las instrucciones es ofender WVINDB ($ 0F, $ 09) el cual puedo detectar de esta manera:
// See if the instruction pointer is a WBINVD opcode :
if (PAnsiChar(E.ExceptionRecord.ExceptionAddress)[0] = #$0F)
and (PAnsiChar(E.ExceptionRecord.ExceptionAddress)[1] = #$09) then
todo esto funciona (siempre que corro esta fuera del depurador), pero no puedo obtener el código para ejecutar más allá de las instrucciones de error - Lo intenté así:
begin
// Skip the WBINVD instruction, and continue execution :
Inc(DWORD(E.ExceptionRecord.ExceptionAddress), 2);
Result := EXCEPTION_CONTINUE_EXECUTION;
Exit;
end;
Alas, eso no funciona. En realidad, habría utilizado el puntero de instrucción real (E.ContextRecord.Eip), pero de alguna manera todo el ContextRecord no parece estar lleno.
¿Qué puedo hacer para que haga funcione según lo previsto?
PD: Al ejecutar con el depurador, esperaría que este código termine en mi rutina ExceptionFilter, pero no funciona, solo funciona sin el depurador; ¿Porque eso?
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!');
Además, SetUnhandledExceptionFilter es una API kernel: http://msdn.microsoft.com/en-us/library/ms680634(VS.85).aspx – PatrickvL
Ah, y al leer la documentación, parece que tiene razón sobre el miembro de Contexto, pero como ya dije, ¡no está poblado! Solo el ExceptionRecord parece cuerdo: el ContextRecord parece no inicializado. – PatrickvL
@PatrickvL: está disponible para XP y versiones posteriores (ver MSDN). Con respecto a SetUnhandledExceptionFilter, los documentos de MSDN dicen: puntero a una función de filtro de excepción de nivel superior que se invocará cada vez que la función UnhandledExceptionFilter obtenga el control y el proceso no se depure. AddVectoredExceptionHandler funciona dentro del depurador así que pruébalo! – Remko