Author: hbelusca
Date: Thu Mar 26 01:46:27 2015
New Revision: 66897

URL: http://svn.reactos.org/svn/reactos?rev=66897&view=rev
Log:
[NTVDM]
Write a proper exception filter for the emulated CPU. Allows to:
- handle memory access exceptions inside the virtual memory space (happens when 
a VDD installs a memory hook on a memory region and a DOS app tries to 
read/write inside this region);
- detect NTVDM bugs (if during emulation one tries to read/write in invalid 
memory areas). This should unveils at least 1 bug in the DOS device emulation, 
when running 386TO486.COM inside NTVDM.

Modified:
    trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c

Modified: trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c?rev=66897&r1=66896&r2=66897&view=diff
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c       [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c       [iso-8859-1] Thu Mar 26 
01:46:27 2015
@@ -112,10 +112,60 @@
     Fast486StepInto(&EmulatorContext);
 }
 
+LONG CpuExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
+{
+    /* Get the exception record */
+    PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;
+
+    switch (ExceptionRecord->ExceptionCode)
+    {
+        /* We only handle access violations so far */
+        case EXCEPTION_ACCESS_VIOLATION:
+        {
+            /* Retrieve the address to which a read or write attempt was made 
*/
+            ULONG_PTR Pointer = ExceptionRecord->ExceptionInformation[1];
+
+            /*
+             * Check whether the access exception was done inside the virtual 
memory space
+             * (caused by an emulated app) or outside (casued by a bug in 
ourselves).
+             */
+            if ((ULONG_PTR)Pointer < (ULONG_PTR)BaseAddress ||
+                (ULONG_PTR)Pointer > (ULONG_PTR)BaseAddress + MAX_ADDRESS)
+            {
+                DPRINT1("NTVDM: Access violation at 0x%p outside the virtual 
memory space!\n", Pointer);
+                return EXCEPTION_CONTINUE_SEARCH;
+            }
+
+            /* We are good to go. Dispatch to our memory handlers. */
+            {
+            BOOLEAN Writing = (ExceptionRecord->ExceptionInformation[0] == 1);
+            ULONG FaultAddress = (ULONG)PHYS_TO_REAL(Pointer);
+
+            /* Fix the CPU state */
+            Fast486Rewind(&EmulatorContext);
+
+            /* Call the handler */
+            MemExceptionHandler(FaultAddress, Writing);
+            }
+
+            // /* Continue executing the exception handler */
+            // return EXCEPTION_EXECUTE_HANDLER;
+            return EXCEPTION_CONTINUE_EXECUTION;
+        }
+
+        default:
+        {
+            DPRINT1("NTVDM: Exception 0x%08lx not handled!\n", 
ExceptionRecord->ExceptionCode);
+            break;
+        }
+    }
+
+    /* Continue to search for a handler */
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
 VOID CpuSimulate(VOID)
 {
-    EXCEPTION_RECORD LocalExceptionRecord;
-
     if (CpuCallLevel > MaxCpuCallLevel)
     {
         DisplayMessage(L"Too many CPU levels of recursion (%d, expected 
maximum %d)",
@@ -135,20 +185,9 @@
         {
             while (VdmRunning && CpuRunning) ClockUpdate();
         }
-        _SEH2_EXCEPT(LocalExceptionRecord = 
*_SEH2_GetExceptionInformation()->ExceptionRecord,
-                     EXCEPTION_EXECUTE_HANDLER)
-        {
-            BOOLEAN Writing = (LocalExceptionRecord.ExceptionInformation[0] == 
1);
-            ULONG FaultAddress = 
(ULONG)PHYS_TO_REAL(LocalExceptionRecord.ExceptionInformation[1]);
-
-            /* Make sure this was an access violation */
-            ASSERT(LocalExceptionRecord.ExceptionCode == 
EXCEPTION_ACCESS_VIOLATION);
-
-            /* Fix the CPU state */
-            Fast486Rewind(&EmulatorContext);
-
-            /* Call the handler */
-            MemExceptionHandler(FaultAddress, Writing);
+        _SEH2_EXCEPT(CpuExceptionFilter(_SEH2_GetExceptionInformation()))
+        {
+            DPRINT1("VDM exception handler called\n");
         }
         _SEH2_END;
     }


Reply via email to