mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Split kernel and user-mode exception handling
svn path=/trunk/; revision=2382
This commit is contained in:
parent
b981b14821
commit
229104bb31
1 changed files with 304 additions and 0 deletions
304
reactos/ntoskrnl/ke/i386/usertrap.c
Normal file
304
reactos/ntoskrnl/ke/i386/usertrap.c
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: ntoskrnl/ke/i386/usertrap.c
|
||||||
|
* PURPOSE: Handling usermode exceptions.
|
||||||
|
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||||
|
* REVISION HISTORY:
|
||||||
|
* 18/11/01: Split from ntoskrnl/ke/i386/exp.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <roscfg.h>
|
||||||
|
#include <internal/ntoskrnl.h>
|
||||||
|
#include <internal/ke.h>
|
||||||
|
#include <internal/i386/segment.h>
|
||||||
|
#include <internal/i386/mm.h>
|
||||||
|
#include <internal/module.h>
|
||||||
|
#include <internal/mm.h>
|
||||||
|
#include <internal/ps.h>
|
||||||
|
#include <internal/trap.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <internal/safe.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
/* GLOBALS *****************************************************************/
|
||||||
|
|
||||||
|
static char *ExceptionTypeStrings[] =
|
||||||
|
{
|
||||||
|
"Divide Error",
|
||||||
|
"Debug Trap",
|
||||||
|
"NMI",
|
||||||
|
"Breakpoint",
|
||||||
|
"Overflow",
|
||||||
|
"BOUND range exceeded",
|
||||||
|
"Invalid Opcode",
|
||||||
|
"No Math Coprocessor",
|
||||||
|
"Double Fault",
|
||||||
|
"Unknown(9)",
|
||||||
|
"Invalid TSS",
|
||||||
|
"Segment Not Present",
|
||||||
|
"Stack Segment Fault",
|
||||||
|
"General Protection",
|
||||||
|
"Page Fault",
|
||||||
|
"Math Fault",
|
||||||
|
"Alignment Check",
|
||||||
|
"Machine Check"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
STATIC BOOLEAN
|
||||||
|
print_user_address(PVOID address)
|
||||||
|
{
|
||||||
|
#ifdef KDBG
|
||||||
|
ULONG Offset;
|
||||||
|
PSYMBOL Symbol, NextSymbol;
|
||||||
|
BOOLEAN Printed = FALSE;
|
||||||
|
ULONG NextAddress;
|
||||||
|
#endif /* KDBG */
|
||||||
|
PLIST_ENTRY current_entry;
|
||||||
|
PLDR_MODULE current;
|
||||||
|
PEPROCESS CurrentProcess;
|
||||||
|
PPEB Peb = NULL;
|
||||||
|
|
||||||
|
CurrentProcess = PsGetCurrentProcess();
|
||||||
|
if (NULL != CurrentProcess)
|
||||||
|
{
|
||||||
|
Peb = CurrentProcess->Peb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == Peb)
|
||||||
|
{
|
||||||
|
DbgPrint("<%x>", address);
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_entry = Peb->Ldr->InLoadOrderModuleList.Flink;
|
||||||
|
|
||||||
|
while (current_entry != &Peb->Ldr->InLoadOrderModuleList &&
|
||||||
|
current_entry != NULL)
|
||||||
|
{
|
||||||
|
current =
|
||||||
|
CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList);
|
||||||
|
|
||||||
|
if (address >= (PVOID)current->BaseAddress &&
|
||||||
|
address < (PVOID)(current->BaseAddress + current->SizeOfImage))
|
||||||
|
{
|
||||||
|
#ifdef KDBG
|
||||||
|
|
||||||
|
Offset = (ULONG)(address - current->BaseAddress);
|
||||||
|
Symbol = current->Symbols.Symbols;
|
||||||
|
while (Symbol != NULL)
|
||||||
|
{
|
||||||
|
NextSymbol = Symbol->Next;
|
||||||
|
if (NextSymbol != NULL)
|
||||||
|
NextAddress = NextSymbol->RelativeAddress;
|
||||||
|
else
|
||||||
|
NextAddress = current->SizeOfImage;
|
||||||
|
|
||||||
|
if ((Offset >= Symbol->RelativeAddress) &&
|
||||||
|
(Offset < NextAddress))
|
||||||
|
{
|
||||||
|
DbgPrint("<%wZ: %x (%wZ)>",
|
||||||
|
¤t->BaseDllName, Offset, &Symbol->Name);
|
||||||
|
Printed = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Symbol = NextSymbol;
|
||||||
|
}
|
||||||
|
if (!Printed)
|
||||||
|
DbgPrint("<%wZ: %x>", ¤t->BaseDllName, Offset);
|
||||||
|
|
||||||
|
#else /* KDBG */
|
||||||
|
|
||||||
|
DbgPrint("<%wZ: %x>", ¤t->BaseDllName,
|
||||||
|
address - current->BaseAddress);
|
||||||
|
|
||||||
|
#endif /* KDBG */
|
||||||
|
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_entry = current_entry->Flink;
|
||||||
|
}
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Disabled until SEH support is implemented.
|
||||||
|
*/
|
||||||
|
ULONG
|
||||||
|
KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
|
||||||
|
{
|
||||||
|
EXCEPTION_RECORD Er;
|
||||||
|
|
||||||
|
if (ExceptionNr == 0)
|
||||||
|
{
|
||||||
|
Er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
|
||||||
|
}
|
||||||
|
else if (ExceptionNr == 1)
|
||||||
|
{
|
||||||
|
Er.ExceptionCode = STATUS_SINGLE_STEP;
|
||||||
|
}
|
||||||
|
else if (ExceptionNr == 3)
|
||||||
|
{
|
||||||
|
Er.ExceptionCode = STATUS_BREAKPOINT;
|
||||||
|
}
|
||||||
|
else if (ExceptionNr == 4)
|
||||||
|
{
|
||||||
|
Er.ExceptionCode = STATUS_INTEGER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else if (ExceptionNr == 5)
|
||||||
|
{
|
||||||
|
Er.ExceptionCode = STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||||
|
}
|
||||||
|
else if (ExceptionNr == 6)
|
||||||
|
{
|
||||||
|
Er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
|
||||||
|
}
|
||||||
|
Er.ExceptionFlags = 0;
|
||||||
|
Er.ExceptionRecord = NULL;
|
||||||
|
Er.ExceptionAddress = (PVOID)Tf->Eip;
|
||||||
|
if (ExceptionNr == 14)
|
||||||
|
{
|
||||||
|
Er.NumberParameters = 2;
|
||||||
|
Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
|
||||||
|
Er.ExceptionInformation[1] = (ULONG)Cr2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Er.NumberParameters = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KiDispatchException(&Er, 0, Tf, UserMode, TRUE);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ULONG
|
||||||
|
KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
|
||||||
|
{
|
||||||
|
PULONG Frame;
|
||||||
|
ULONG cr3;
|
||||||
|
ULONG i;
|
||||||
|
ULONG ReturnAddress;
|
||||||
|
ULONG NextFrame;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the PDBR
|
||||||
|
*/
|
||||||
|
__asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print out the CPU registers
|
||||||
|
*/
|
||||||
|
if (ExceptionNr < 19)
|
||||||
|
{
|
||||||
|
DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
|
||||||
|
ExceptionNr, Tf->ErrorCode&0xffff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
|
||||||
|
}
|
||||||
|
DbgPrint("CS:EIP %x:%x ", Tf->Cs&0xffff, Tf->Eip);
|
||||||
|
print_user_address((PVOID)Tf->Eip);
|
||||||
|
DbgPrint("\n");
|
||||||
|
__asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
|
||||||
|
DbgPrint("CR2 %x CR3 %x ", Cr2, cr3);
|
||||||
|
DbgPrint("Process: %x ",PsGetCurrentProcess());
|
||||||
|
if (PsGetCurrentProcess() != NULL)
|
||||||
|
{
|
||||||
|
DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
|
||||||
|
DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
|
||||||
|
}
|
||||||
|
if (PsGetCurrentThread() != NULL)
|
||||||
|
{
|
||||||
|
DbgPrint("Thrd: %x Tid: %x",
|
||||||
|
PsGetCurrentThread(),
|
||||||
|
PsGetCurrentThread()->Cid.UniqueThread);
|
||||||
|
}
|
||||||
|
DbgPrint("\n");
|
||||||
|
DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
|
||||||
|
Tf->Fs&0xffff, Tf->Gs&0xfff);
|
||||||
|
DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
|
||||||
|
DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf->Edx, Tf->Ebp, Tf->Esi);
|
||||||
|
DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
|
||||||
|
DbgPrint("SS:ESP %x:%x\n", Tf->Ss, Tf->Esp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump the stack frames
|
||||||
|
*/
|
||||||
|
DbgPrint("Frames: ");
|
||||||
|
i = 1;
|
||||||
|
Frame = (PULONG)Tf->Ebp;
|
||||||
|
while (Frame != NULL && i < 50)
|
||||||
|
{
|
||||||
|
Status = MmCopyFromCaller(&ReturnAddress, &Frame[1], sizeof(ULONG));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DbgPrint("????????\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
print_user_address((PVOID)ReturnAddress);
|
||||||
|
Status = MmCopyFromCaller(&NextFrame, &Frame[0], sizeof(ULONG));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DbgPrint("Frame is inaccessible.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((NextFrame + sizeof(ULONG)) >= KERNEL_BASE)
|
||||||
|
{
|
||||||
|
DbgPrint("Next frame is in kernel space!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (NextFrame >= (ULONG)Frame)
|
||||||
|
{
|
||||||
|
DbgPrint("Next frame is not below current frame!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Frame = (PULONG)NextFrame;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kill the faulting task
|
||||||
|
*/
|
||||||
|
__asm__("sti\n\t");
|
||||||
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_NONCONTINUABLE_EXCEPTION);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If terminating the process fails then bugcheck
|
||||||
|
*/
|
||||||
|
KeBugCheck(0);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in a new issue