exp.c
来自「一个类似windows」· C语言 代码 · 共 1,362 行 · 第 1/3 页
C
1,362 行
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ke/i386/exp.c
* PURPOSE: Exception Support Code
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Gregor Anich
* David Welch (welch@cwcom.net)
* Skywing (skywing@valhallalegends.com)
*/
/*
* FIXMES:
* - Clean up file (remove all stack functions and use RtlWalkFrameChain/RtlCaptureStackBacktrace)
* - Sanitize some context fields.
* - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
* - Forward exceptions to user-mode debugger.
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, KeInitExceptions)
#endif
VOID
NTAPI
Ki386AdjustEsp0(
IN PKTRAP_FRAME TrapFrame
);
extern KIDTENTRY KiIdt[];
/* GLOBALS *****************************************************************/
#define FLAG_IF (1<<9)
#define _STR(x) #x
#define STR(x) _STR(x)
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
#endif
extern ULONG init_stack;
extern ULONG init_stack_top;
extern BOOLEAN Ke386NoExecute;
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",
"Reserved(15)",
"Math Fault",
"Alignment Check",
"Machine Check",
"SIMD Fault"
};
NTSTATUS ExceptionToNtStatus[] =
{
STATUS_INTEGER_DIVIDE_BY_ZERO,
STATUS_SINGLE_STEP,
STATUS_ACCESS_VIOLATION,
STATUS_BREAKPOINT,
STATUS_INTEGER_OVERFLOW,
STATUS_ARRAY_BOUNDS_EXCEEDED,
STATUS_ILLEGAL_INSTRUCTION,
STATUS_FLOAT_INVALID_OPERATION,
STATUS_ACCESS_VIOLATION,
STATUS_ACCESS_VIOLATION,
STATUS_ACCESS_VIOLATION,
STATUS_ACCESS_VIOLATION,
STATUS_STACK_OVERFLOW,
STATUS_ACCESS_VIOLATION,
STATUS_ACCESS_VIOLATION,
STATUS_ACCESS_VIOLATION, /* RESERVED */
STATUS_FLOAT_INVALID_OPERATION, /* Should not be used, the FPU can give more specific info */
STATUS_DATATYPE_MISALIGNMENT,
STATUS_ACCESS_VIOLATION,
STATUS_FLOAT_MULTIPLE_TRAPS,
};
/* FUNCTIONS ****************************************************************/
BOOLEAN STDCALL
KiRosPrintAddress(PVOID address)
{
PLIST_ENTRY current_entry;
PLDR_DATA_TABLE_ENTRY current;
extern LIST_ENTRY ModuleListHead;
ULONG_PTR RelativeAddress;
ULONG i = 0;
do
{
current_entry = ModuleListHead.Flink;
while (current_entry != &ModuleListHead)
{
current =
CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
if (address >= (PVOID)current->DllBase &&
address < (PVOID)((ULONG_PTR)current->DllBase + current->SizeOfImage))
{
RelativeAddress = (ULONG_PTR) address - (ULONG_PTR) current->DllBase;
DbgPrint("<%wZ: %x>", ¤t->FullDllName, RelativeAddress);
return(TRUE);
}
current_entry = current_entry->Flink;
}
address = (PVOID)((ULONG_PTR)address & ~(ULONG_PTR)MmSystemRangeStart);
} while(++i <= 1);
return(FALSE);
}
ULONG
KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
{
EXCEPTION_RECORD Er;
Er.ExceptionFlags = 0;
Er.ExceptionRecord = NULL;
Er.ExceptionAddress = (PVOID)Tf->Eip;
if (ExceptionNr == 14)
{
Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
Er.NumberParameters = 2;
Er.ExceptionInformation[0] = Tf->ErrCode & 0x1;
Er.ExceptionInformation[1] = (ULONG)Cr2;
}
else
{
if (ExceptionNr < ARRAY_SIZE(ExceptionToNtStatus))
{
Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
}
else
{
Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
}
Er.NumberParameters = 0;
}
/* FIXME: Which exceptions are noncontinuable? */
Er.ExceptionFlags = 0;
KiDispatchException(&Er, NULL, Tf, KernelMode, TRUE);
return(0);
}
VOID
KiDoubleFaultHandler(VOID)
{
#if 0
unsigned int cr2;
ULONG StackLimit;
ULONG StackBase;
ULONG Esp0;
ULONG ExceptionNr = 8;
KTSS* OldTss;
PULONG Frame;
ULONG OldCr3;
#if 0
ULONG i, j;
static PVOID StackTrace[MM_STACK_SIZE / sizeof(PVOID)];
static ULONG StackRepeatCount[MM_STACK_SIZE / sizeof(PVOID)];
static ULONG StackRepeatLength[MM_STACK_SIZE / sizeof(PVOID)];
ULONG TraceLength;
BOOLEAN FoundRepeat;
#endif
OldTss = KeGetCurrentKPCR()->TSS;
Esp0 = OldTss->Esp0;
/* Get CR2 */
cr2 = Ke386GetCr2();
if (PsGetCurrentThread() != NULL &&
PsGetCurrentThread()->ThreadsProcess != NULL)
{
OldCr3 = (ULONG)
PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart;
}
else
{
OldCr3 = 0xBEADF0AL;
}
/*
* Check for stack underflow
*/
if (PsGetCurrentThread() != NULL &&
Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
{
DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
ExceptionNr = 12;
}
/*
* Print out the CPU registers
*/
if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
{
DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
ExceptionNr, 0);
}
else
{
DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
}
DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
KeRosPrintAddress((PVOID)OldTss->Eip);
DbgPrint("\n");
DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
DbgPrint("Proc: %x ",PsGetCurrentProcess());
if (PsGetCurrentProcess() != NULL)
{
DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
DbgPrint("%.16s> ", 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", OldTss->Ds, OldTss->Es,
OldTss->Fs, OldTss->Gs);
DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
OldTss->Ecx);
DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\nESP: %.8x ", OldTss->Edx,
OldTss->Ebp, OldTss->Esi, Esp0);
DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
if (OldTss->Cs == KGDT_R0_CODE)
{
DbgPrint("kESP %.8x ", Esp0);
if (PsGetCurrentThread() != NULL)
{
DbgPrint("kernel stack base %x\n",
PsGetCurrentThread()->Tcb.StackLimit);
}
}
else
{
DbgPrint("User ESP %.8x\n", OldTss->Esp);
}
if ((OldTss->Cs & 0xffff) == KGDT_R0_CODE)
{
if (PsGetCurrentThread() != NULL)
{
StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit;
}
else
{
StackLimit = (ULONG)init_stack_top;
StackBase = (ULONG)init_stack;
}
/*
Change to an #if 0 to reduce the amount of information printed on
a recursive stack trace.
*/
#if 1
DbgPrint("Frames: ");
Frame = (PULONG)OldTss->Ebp;
while (Frame != NULL && (ULONG)Frame >= StackBase)
{
KeRosPrintAddress((PVOID)Frame[1]);
Frame = (PULONG)Frame[0];
DbgPrint("\n");
}
#else
DbgPrint("Frames: ");
i = 0;
Frame = (PULONG)OldTss->Ebp;
while (Frame != NULL && (ULONG)Frame >= StackBase)
{
StackTrace[i] = (PVOID)Frame[1];
Frame = (PULONG)Frame[0];
i++;
}
TraceLength = i;
i = 0;
while (i < TraceLength)
{
StackRepeatCount[i] = 0;
j = i + 1;
FoundRepeat = FALSE;
while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE)
{
if (memcmp(&StackTrace[i], &StackTrace[j],
(j - i) * sizeof(PVOID)) == 0)
{
StackRepeatCount[i] = 2;
StackRepeatLength[i] = j - i;
FoundRepeat = TRUE;
}
else
{
j++;
}
}
if (FoundRepeat == FALSE)
{
i++;
continue;
}
j = j + StackRepeatLength[i];
while ((TraceLength - j) >= StackRepeatLength[i] &&
FoundRepeat == TRUE)
{
if (memcmp(&StackTrace[i], &StackTrace[j],
StackRepeatLength[i] * sizeof(PVOID)) == 0)
{
StackRepeatCount[i]++;
j = j + StackRepeatLength[i];
}
else
{
FoundRepeat = FALSE;
}
}
i = j;
}
i = 0;
while (i < TraceLength)
{
if (StackRepeatCount[i] == 0)
{
KeRosPrintAddress(StackTrace[i]);
i++;
}
else
{
DbgPrint("{");
if (StackRepeatLength[i] == 0)
{
for(;;);
}
for (j = 0; j < StackRepeatLength[i]; j++)
{
KeRosPrintAddress(StackTrace[i + j]);
}
DbgPrint("}*%d", StackRepeatCount[i]);
i = i + StackRepeatLength[i] * StackRepeatCount[i];
}
}
#endif
}
#endif
DbgPrint("\n");
for(;;);
}
VOID
NTAPI
KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
{
ULONG cr3_;
ULONG StackLimit;
ULONG Esp0;
ULONG ExceptionNr = (ULONG)Tf->DbgArgMark;
ULONG cr2 = (ULONG)Tf->DbgArgPointer;
Esp0 = (ULONG)Tf;
/*
* Print out the CPU registers
*/
if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
{
DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
ExceptionNr, Tf->ErrCode&0xffff);
}
else
{
DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrCode&0xffff);
}
DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
Tf->SegCs&0xffff, Tf->Eip);
KeRosPrintAddress((PVOID)Tf->Eip);
DbgPrint("\n");
Ke386GetPageTableDirectory(cr3_);
DbgPrint("cr2 %x cr3 %x ", cr2, cr3_);
DbgPrint("Proc: %x ",PsGetCurrentProcess());
if (PsGetCurrentProcess() != NULL)
{
DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
DbgPrint("%.16s> ", 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->SegDs&0xffff, Tf->SegEs&0xffff,
Tf->SegFs&0xffff, Tf->SegGs&0xfff);
DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf->Edx,
Tf->Ebp, Tf->Esi, Esp0);
DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->EFlags);
if ((Tf->SegCs&0xffff) == KGDT_R0_CODE)
{
DbgPrint("kESP %.8x ", Esp0);
if (PsGetCurrentThread() != NULL)
{
DbgPrint("kernel stack base %x\n",
PsGetCurrentThread()->Tcb.StackLimit);
}
}
if (PsGetCurrentThread() != NULL)
{
StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
}
else
{
StackLimit = (ULONG)init_stack_top;
}
/*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?