From 91a35b7ec11b661e627713b8c0e740a1103aaeae Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Thu, 29 Apr 2010 16:39:52 +0000 Subject: [PATCH] [NTOSKRNL] - On backtraces, print the address of the call instruction (assumed 5 bytes lentgh) instead of the return address, which in many cases does not make sense. (WinDbg does it this way, too) - Fix Ke386SaveFpuState to store the fpu state in the buffer, but in the pointer to the buffer - Anable Ke386SaveFpuState to save the floating point state in KiNpxHandler and KiTrap13Handler, so we know what error we got. - Disable saving debug registers in the trap frame, as long as the kernel doesn't support this - Fixes ntdll_winetest exception / OllyDbg freeze/reboot See issue #5301 for more details. svn path=/trunk/; revision=47060 --- .../ntoskrnl/include/internal/i386/intrin_i.h | 4 +- reactos/ntoskrnl/kdbg/kdb_cli.c | 3 +- reactos/ntoskrnl/ke/i386/exp.c | 2 +- reactos/ntoskrnl/ke/i386/traphdlr.c | 104 +++++++++--------- 4 files changed, 57 insertions(+), 56 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/i386/intrin_i.h b/reactos/ntoskrnl/include/internal/i386/intrin_i.h index 94501841149..6cb2a7cbf0a 100644 --- a/reactos/ntoskrnl/include/internal/i386/intrin_i.h +++ b/reactos/ntoskrnl/include/internal/i386/intrin_i.h @@ -42,11 +42,11 @@ Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea) extern ULONG KeI386FxsrPresent; if (KeI386FxsrPresent) { - __asm__ __volatile__ ("fxsave %0\n" : : "m"(SaveArea)); + __asm__ __volatile__ ("fxsave %0\n" : : "m"(*SaveArea)); } else { - __asm__ __volatile__ ("fnsave %0\n wait\n" : : "m"(SaveArea)); + __asm__ __volatile__ ("fnsave %0\n wait\n" : : "m"(*SaveArea)); } } diff --git a/reactos/ntoskrnl/kdbg/kdb_cli.c b/reactos/ntoskrnl/kdbg/kdb_cli.c index fa42826c9fa..4c469fd3721 100644 --- a/reactos/ntoskrnl/kdbg/kdb_cli.c +++ b/reactos/ntoskrnl/kdbg/kdb_cli.c @@ -823,7 +823,8 @@ KdbpCmdBackTrace( break; } - if (!KdbSymPrintAddress((PVOID)Address)) + /* Print the location of the call instruction */ + if (!KdbSymPrintAddress((PVOID)(Address - 5))) KdbpPrint("<%08x>\n", Address); else KdbpPrint("\n"); diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index 284ff19e3bf..38dded77062 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -584,7 +584,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, } /* Handle the Debug Registers */ - if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) + if (0 && (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) { /* Loop DR registers */ for (i = 0; i < 4; i++) diff --git a/reactos/ntoskrnl/ke/i386/traphdlr.c b/reactos/ntoskrnl/ke/i386/traphdlr.c index f9a954ec298..b9033c2069e 100644 --- a/reactos/ntoskrnl/ke/i386/traphdlr.c +++ b/reactos/ntoskrnl/ke/i386/traphdlr.c @@ -240,7 +240,7 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame, } /* User or kernel trap -- get ready to issue an exception */ - if (Thread->NpxState == NPX_STATE_NOT_LOADED) + //if (Thread->NpxState == NPX_STATE_NOT_LOADED) { /* Update CR0 */ Cr0 = __readcr0(); @@ -248,7 +248,7 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame, __writecr0(Cr0); /* Save FPU state */ - //Ke386SaveFpuState(SaveArea); + Ke386SaveFpuState(SaveArea); /* Mark CR0 state dirty */ Cr0 |= NPX_STATE_NOT_LOADED; @@ -1082,64 +1082,64 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame) * we should probably table this for now since it's not a "real" issue. */ - /* - * NOTE2: Another scenario is the IRET during a V8086 restore (BIOS Call) - * which will cause a GPF since the trap frame is a total mess (on purpose) - * as built in KiEnterV86Mode. - * - * The idea is to scan for IRET, scan for the known EIP adress, validate CS - * and then manually issue a jump to the V8086 return EIP. - */ - Instructions = (PUCHAR)TrapFrame->Eip; - if (Instructions[0] == 0xCF) - { - /* - * Some evil shit is going on here -- this is not the SS:ESP you're - * looking for! Instead, this is actually CS:EIP you're looking at! - * Why? Because part of the trap frame actually corresponds to the IRET - * stack during the trap exit! - */ - if ((TrapFrame->HardwareEsp == (ULONG)Ki386BiosCallReturnAddress) && - (TrapFrame->HardwareSegSs == (KGDT_R0_CODE | RPL_MASK))) - { - /* Exit the V86 trap! */ - Ki386BiosCallReturnAddress(TrapFrame); - } - else - { - /* Otherwise, this is another kind of IRET fault */ - UNIMPLEMENTED; - while (TRUE); - } - } + /* + * NOTE2: Another scenario is the IRET during a V8086 restore (BIOS Call) + * which will cause a GPF since the trap frame is a total mess (on purpose) + * as built in KiEnterV86Mode. + * + * The idea is to scan for IRET, scan for the known EIP adress, validate CS + * and then manually issue a jump to the V8086 return EIP. + */ + Instructions = (PUCHAR)TrapFrame->Eip; + if (Instructions[0] == 0xCF) + { + /* + * Some evil shit is going on here -- this is not the SS:ESP you're + * looking for! Instead, this is actually CS:EIP you're looking at! + * Why? Because part of the trap frame actually corresponds to the IRET + * stack during the trap exit! + */ + if ((TrapFrame->HardwareEsp == (ULONG)Ki386BiosCallReturnAddress) && + (TrapFrame->HardwareSegSs == (KGDT_R0_CODE | RPL_MASK))) + { + /* Exit the V86 trap! */ + Ki386BiosCallReturnAddress(TrapFrame); + } + else + { + /* Otherwise, this is another kind of IRET fault */ + UNIMPLEMENTED; + while (TRUE); + } + } /* So since we're not dealing with the above case, check for RDMSR/WRMSR */ - if ((Instructions[0] == 0xF) && // 2-byte opcode + if ((Instructions[0] == 0xF) && // 2-byte opcode (((Instructions[1] >> 8) == 0x30) || // RDMSR ((Instructions[2] >> 8) == 0x32))) // WRMSR - { + { /* Unknown CPU MSR, so raise an access violation */ KiDispatchException0Args(STATUS_ACCESS_VIOLATION, TrapFrame->Eip, TrapFrame); - } - - /* Check for lazy segment load */ - if (TrapFrame->SegDs != (KGDT_R3_DATA | RPL_MASK)) - { - /* Fix it */ - TrapFrame->SegDs = (KGDT_R3_DATA | RPL_MASK); - } - else if (TrapFrame->SegEs != (KGDT_R3_DATA | RPL_MASK)) - { + } + + /* Check for lazy segment load */ + if (TrapFrame->SegDs != (KGDT_R3_DATA | RPL_MASK)) + { + /* Fix it */ + TrapFrame->SegDs = (KGDT_R3_DATA | RPL_MASK); + } + else if (TrapFrame->SegEs != (KGDT_R3_DATA | RPL_MASK)) + { /* Fix it */ TrapFrame->SegEs = (KGDT_R3_DATA | RPL_MASK); - } - else - { - /* Whatever it is, we can't handle it */ - KiSystemFatalException(EXCEPTION_GP_FAULT, TrapFrame); - } + } + else + { + /* Whatever it is, we can't handle it */ + KiSystemFatalException(EXCEPTION_GP_FAULT, TrapFrame); + } /* Return to where we came from */ KiTrapReturn(TrapFrame); @@ -1353,7 +1353,7 @@ KiTrap13Handler(IN PKTRAP_FRAME TrapFrame) __writecr0(Cr0); /* Save FPU state */ - //Ke386SaveFpuState(SaveArea); + Ke386SaveFpuState(SaveArea); /* Mark CR0 state dirty */ Cr0 |= NPX_STATE_NOT_LOADED; @@ -1379,7 +1379,7 @@ KiTrap13Handler(IN PKTRAP_FRAME TrapFrame) FSW_UNDERFLOW | FSW_PRECISION); Error &= MxCsrMask; - + /* Now handle any of those legal errors */ if (Error & (FSW_INVALID_OPERATION | FSW_DENORMAL | -- 2.17.1