3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/i386/usertrap.c
22 * PURPOSE: Handling usermode exceptions.
23 * PROGRAMMER: David Welch (welch@cwcom.net)
25 * 18/11/01: Split from ntoskrnl/ke/i386/exp.c
28 /* INCLUDES *****************************************************************/
31 //#include <ntdll/ldr.h>
34 #include <internal/debug.h>
37 /* GLOBALS *****************************************************************/
39 static char *ExceptionTypeStrings
[] =
46 "BOUND range exceeded",
48 "No Math Coprocessor",
52 "Segment Not Present",
53 "Stack Segment Fault",
61 /* FUNCTIONS ****************************************************************/
64 print_user_address(PVOID address
)
66 PLIST_ENTRY current_entry
;
68 PEPROCESS CurrentProcess
;
70 ULONG_PTR RelativeAddress
;
74 CurrentProcess
= PsGetCurrentProcess();
75 if (NULL
!= CurrentProcess
)
77 Peb
= CurrentProcess
->Peb
;
82 DbgPrint("<%x>", address
);
86 Status
= MmSafeCopyFromUser(&Ldr
, &Peb
->Ldr
, sizeof(PPEB_LDR_DATA
));
87 if (!NT_SUCCESS(Status
))
89 DbgPrint("<%x>", address
);
92 current_entry
= Ldr
->InLoadOrderModuleList
.Flink
;
94 while (current_entry
!= &Ldr
->InLoadOrderModuleList
&&
95 current_entry
!= NULL
)
98 CONTAINING_RECORD(current_entry
, LDR_MODULE
, InLoadOrderModuleList
);
100 if (address
>= (PVOID
)current
->BaseAddress
&&
101 address
< (PVOID
)(current
->BaseAddress
+ current
->SizeOfImage
))
104 (ULONG_PTR
) address
- (ULONG_PTR
)current
->BaseAddress
;
105 DbgPrint("<%wZ: %x>", ¤t
->BaseDllName
, RelativeAddress
);
109 current_entry
= current_entry
->Flink
;
116 * Disabled until SEH support is implemented.
119 KiUserTrapHandler(PKTRAP_FRAME Tf
, ULONG ExceptionNr
, PVOID Cr2
)
123 if (ExceptionNr
== 0)
125 Er
.ExceptionCode
= STATUS_INTEGER_DIVIDE_BY_ZERO
;
127 else if (ExceptionNr
== 1)
129 Er
.ExceptionCode
= STATUS_SINGLE_STEP
;
131 else if (ExceptionNr
== 3)
133 Er
.ExceptionCode
= STATUS_BREAKPOINT
;
135 else if (ExceptionNr
== 4)
137 Er
.ExceptionCode
= STATUS_INTEGER_OVERFLOW
;
139 else if (ExceptionNr
== 5)
141 Er
.ExceptionCode
= STATUS_ARRAY_BOUNDS_EXCEEDED
;
143 else if (ExceptionNr
== 6)
145 Er
.ExceptionCode
= STATUS_ILLEGAL_INSTRUCTION
;
149 Er
.ExceptionCode
= STATUS_ACCESS_VIOLATION
;
151 Er
.ExceptionFlags
= 0;
152 Er
.ExceptionRecord
= NULL
;
153 Er
.ExceptionAddress
= (PVOID
)Tf
->Eip
;
154 if (ExceptionNr
== 14)
156 Er
.NumberParameters
= 2;
157 Er
.ExceptionInformation
[0] = Tf
->ErrorCode
& 0x1;
158 Er
.ExceptionInformation
[1] = (ULONG
)Cr2
;
162 Er
.NumberParameters
= 0;
166 KiDispatchException(&Er
, 0, Tf
, UserMode
, TRUE
);
171 KiUserTrapHandler(PKTRAP_FRAME Tf
, ULONG ExceptionNr
, PVOID Cr2
)
183 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3
));
186 * Print out the CPU registers
188 if (ExceptionNr
< 19)
190 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings
[ExceptionNr
],
191 ExceptionNr
, Tf
->ErrorCode
&0xffff);
195 DbgPrint("Exception: %d(%x)\n", ExceptionNr
, Tf
->ErrorCode
&0xffff);
197 DbgPrint("CS:EIP %x:%x ", Tf
->Cs
&0xffff, Tf
->Eip
);
198 print_user_address((PVOID
)Tf
->Eip
);
200 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3
));
201 DbgPrint("CR2 %x CR3 %x ", Cr2
, cr3
);
202 DbgPrint("Process: %x ",PsGetCurrentProcess());
203 if (PsGetCurrentProcess() != NULL
)
205 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId
);
206 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName
);
208 if (PsGetCurrentThread() != NULL
)
210 DbgPrint("Thrd: %x Tid: %x",
211 PsGetCurrentThread(),
212 PsGetCurrentThread()->Cid
.UniqueThread
);
215 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf
->Ds
&0xffff, Tf
->Es
&0xffff,
216 Tf
->Fs
&0xffff, Tf
->Gs
&0xfff);
217 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf
->Eax
, Tf
->Ebx
, Tf
->Ecx
);
218 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf
->Edx
, Tf
->Ebp
, Tf
->Esi
);
219 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf
->Edi
, Tf
->Eflags
);
220 DbgPrint("SS:ESP %x:%x\n", Tf
->Ss
, Tf
->Esp
);
223 * Dump the stack frames
225 DbgPrint("Frames: ");
227 Frame
= (PULONG
)Tf
->Ebp
;
228 while (Frame
!= NULL
&& i
< 50)
230 Status
= MmSafeCopyFromUser(&ReturnAddress
, &Frame
[1], sizeof(ULONG
));
231 if (!NT_SUCCESS(Status
))
233 DbgPrint("????????\n");
236 print_user_address((PVOID
)ReturnAddress
);
237 Status
= MmSafeCopyFromUser(&NextFrame
, &Frame
[0], sizeof(ULONG
));
238 if (!NT_SUCCESS(Status
))
240 DbgPrint("Frame is inaccessible.\n");
243 if ((NextFrame
+ sizeof(ULONG
)) >= KERNEL_BASE
)
245 DbgPrint("Next frame is in kernel space!\n");
248 if (NextFrame
!= 0 && NextFrame
<= (ULONG
)Frame
)
250 DbgPrint("Next frame is not above current frame!\n");
253 Frame
= (PULONG
)NextFrame
;
258 * Kill the faulting process
261 ZwTerminateProcess(NtCurrentProcess(), STATUS_NONCONTINUABLE_EXCEPTION
);
264 * If terminating the process fails then bugcheck