2010-12-03 13 views
5

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!'); 

Respuesta

3

SetUnhandledExceptionFilter parece ser algún tipo de envoltorio Delphi, tal vez tenga más suerte si lo hace directamente?

Puede registrar su propio controlador de excepción con AddVectoredExceptionHandler, esto llamará a una función callback que le da una estructura EXCEPTION_POINTERS. El miembro de contexto de esa estructura devuelve un EIP que puede modificar.

Si devuelve EXCEPTION_CONTINUE_EXECUTION en la ejecución de devolución de llamada continúa en el EIP determinado.

+1

Además, SetUnhandledExceptionFilter es una API kernel: http://msdn.microsoft.com/en-us/library/ms680634(VS.85).aspx – PatrickvL

+0

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

+0

@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

Cuestiones relacionadas