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/…
==============================================================================
--- 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;
}