[NTOS:KE] Improvements for the Trap02 (NMI) and Trap08 (double-fault) exception handlers.

- Add FRAME_TSS FPO debug information for Trap02 and Trap08.
- Switch the active TSS in Trap08 in the very same way as is done in Trap02.

This allows to correctly debug NMI and double-fault exceptions with WinDbg,
by following the different TSS contexts, as described in:
https://blogs.msdn.microsoft.com/debuggingtoolbox/2008/02/22/special-command-analyzing-and-reconstructing-the-stack-using-the-k-command-and-its-variations/
https://blogs.msdn.microsoft.com/ntdebugging/2009/11/25/part-1-got-stack-no-we-ran-out-of-kernel-mode-stack-and-kv-wont-tell-me-why/
http://www.osronline.com/article.cfm?article=254 and http://www.osronline.com/article.cfm?article=328
This commit is contained in:
Hermès Bélusca-Maïto 2019-02-04 01:16:29 +01:00
parent d15e36a1f1
commit 3c8f19eb21
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
4 changed files with 66 additions and 9 deletions

View file

@ -249,6 +249,22 @@ MACRO(TRAP_ENTRY, Trap, Flags)
.ENDP
ENDM
MACRO(TASK_ENTRY, Trap, Flags)
// EXTERN @&Trap&Handler@0 :PROC
EXTERN _&Trap&Handler :PROC
PUBLIC _&Trap
.PROC _&Trap
/* Generate proper debugging symbols */
FPO 0, 0, 0, 0, 0, FRAME_TSS
// /* Common code to create the trap frame */
// KiEnterTrap Flags
/* Call the C handler */
KiCallHandler _&Trap&Handler // @&Trap&Handler@0
.ENDP
ENDM
#define KI_RESTORE_EAX HEX(0001)
#define KI_RESTORE_ECX_EDX HEX(0002)
#define KI_RESTORE_FS HEX(0004)

View file

@ -575,7 +575,7 @@ extern ULONG KeI386CpuStep;
extern ULONG KiFastSystemCallDisable;
extern UCHAR KiDebugRegisterTrapOffsets[9];
extern UCHAR KiDebugRegisterContextOffsets[9];
extern DECLSPEC_NORETURN VOID __cdecl KiTrap02(VOID);
extern VOID __cdecl KiTrap02(VOID);
extern VOID __cdecl KiTrap08(VOID);
extern VOID __cdecl KiTrap13(VOID);
extern VOID __cdecl KiFastCallEntry(VOID);

View file

@ -27,8 +27,6 @@ _KiUnexpectedInterrupt&Vector:
//.endfunc
ENDM
EXTERN _KiTrap02:PROC
/* GLOBALS *******************************************************************/
.data
@ -99,12 +97,13 @@ ENDR
TRAP_ENTRY KiTrap00, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap01, KI_PUSH_FAKE_ERROR_CODE
TASK_ENTRY KiTrap02, 0
TRAP_ENTRY KiTrap03, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap04, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap05, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap06, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap07, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap08, 0
TASK_ENTRY KiTrap08, 0
TRAP_ENTRY KiTrap09, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap0A, 0
TRAP_ENTRY KiTrap0B, 0

View file

@ -458,7 +458,7 @@ KiTrap01Handler(IN PKTRAP_FRAME TrapFrame)
DECLSPEC_NORETURN
VOID
__cdecl
KiTrap02(VOID)
KiTrap02Handler(VOID)
{
PKTSS Tss, NmiTss;
PKTHREAD Thread;
@ -829,11 +829,53 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
DECLSPEC_NORETURN
VOID
FASTCALL
KiTrap08Handler(IN PKTRAP_FRAME TrapFrame)
__cdecl
KiTrap08Handler(VOID)
{
/* FIXME: Not handled */
KiSystemFatalException(EXCEPTION_DOUBLE_FAULT, TrapFrame);
PKTSS Tss, DfTss;
PKTHREAD Thread;
PKPROCESS Process;
PKGDTENTRY TssGdt;
/* For sanity's sake, make sure interrupts are disabled */
_disable();
/* Get the current TSS, thread, and process */
Tss = KeGetPcr()->TSS;
Thread = ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
Process = Thread->ApcState.Process;
/* Save data usually not present in the TSS */
Tss->CR3 = Process->DirectoryTableBase[0];
Tss->IoMapBase = Process->IopmOffset;
Tss->LDT = Process->LdtDescriptor.LimitLow ? KGDT_LDT : 0;
/* Now get the base address of the double-fault TSS */
TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_DF_TSS / sizeof(KGDTENTRY)];
DfTss = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
TssGdt->HighWord.Bytes.BaseMid << 16 |
TssGdt->HighWord.Bytes.BaseHi << 24);
/*
* Switch to it and activate it, masking off the nested flag.
*
* Note that in reality, we are already on the double-fault TSS
* -- we just need to update the PCR to reflect this.
*/
KeGetPcr()->TSS = DfTss;
__writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
TssGdt->HighWord.Bits.Dpl = 0;
TssGdt->HighWord.Bits.Pres = 1;
// TssGdt->HighWord.Bits.Type &= ~0x2; /* I386_ACTIVE_TSS --> I386_TSS */
TssGdt->HighWord.Bits.Type = I386_TSS; // Busy bit cleared in the TSS selector.
/* Bugcheck the system */
KeBugCheckWithTf(UNEXPECTED_KERNEL_MODE_TRAP,
EXCEPTION_DOUBLE_FAULT,
(ULONG_PTR)Tss,
0,
0,
NULL);
}
DECLSPEC_NORETURN