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 *****************************************************************/
30 #include <ddk/ntddk.h>
32 #include <internal/ntoskrnl.h>
33 #include <internal/ke.h>
34 #include <internal/i386/segment.h>
35 #include <internal/i386/mm.h>
36 #include <internal/module.h>
37 #include <internal/mm.h>
38 #include <internal/ps.h>
39 #include <internal/trap.h>
40 #include <ntdll/ldr.h>
41 #include <internal/safe.h>
44 #include <internal/debug.h>
46 /* GLOBALS *****************************************************************/
48 static char *ExceptionTypeStrings
[] =
55 "BOUND range exceeded",
57 "No Math Coprocessor",
61 "Segment Not Present",
62 "Stack Segment Fault",
70 /* FUNCTIONS ****************************************************************/
73 print_user_address(PVOID address
)
75 PLIST_ENTRY current_entry
;
77 PEPROCESS CurrentProcess
;
79 ULONG_PTR RelativeAddress
;
81 CurrentProcess
= PsGetCurrentProcess();
82 if (NULL
!= CurrentProcess
)
84 Peb
= CurrentProcess
->Peb
;
89 DbgPrint("<%x>", address
);
93 current_entry
= Peb
->Ldr
->InLoadOrderModuleList
.Flink
;
95 while (current_entry
!= &Peb
->Ldr
->InLoadOrderModuleList
&&
96 current_entry
!= NULL
)
99 CONTAINING_RECORD(current_entry
, LDR_MODULE
, InLoadOrderModuleList
);
101 if (address
>= (PVOID
)current
->BaseAddress
&&
102 address
< (PVOID
)(current
->BaseAddress
+ current
->SizeOfImage
))
105 (ULONG_PTR
) address
- (ULONG_PTR
)current
->BaseAddress
;
106 DbgPrint("<%wZ: %x>", ¤t
->BaseDllName
, RelativeAddress
);
110 current_entry
= current_entry
->Flink
;
117 * Disabled until SEH support is implemented.
120 KiUserTrapHandler(PKTRAP_FRAME Tf
, ULONG ExceptionNr
, PVOID Cr2
)
124 if (ExceptionNr
== 0)
126 Er
.ExceptionCode
= STATUS_INTEGER_DIVIDE_BY_ZERO
;
128 else if (ExceptionNr
== 1)
130 Er
.ExceptionCode
= STATUS_SINGLE_STEP
;
132 else if (ExceptionNr
== 3)
134 Er
.ExceptionCode
= STATUS_BREAKPOINT
;
136 else if (ExceptionNr
== 4)
138 Er
.ExceptionCode
= STATUS_INTEGER_OVERFLOW
;
140 else if (ExceptionNr
== 5)
142 Er
.ExceptionCode
= STATUS_ARRAY_BOUNDS_EXCEEDED
;
144 else if (ExceptionNr
== 6)
146 Er
.ExceptionCode
= STATUS_ILLEGAL_INSTRUCTION
;
150 Er
.ExceptionCode
= STATUS_ACCESS_VIOLATION
;
152 Er
.ExceptionFlags
= 0;
153 Er
.ExceptionRecord
= NULL
;
154 Er
.ExceptionAddress
= (PVOID
)Tf
->Eip
;
155 if (ExceptionNr
== 14)
157 Er
.NumberParameters
= 2;
158 Er
.ExceptionInformation
[0] = Tf
->ErrorCode
& 0x1;
159 Er
.ExceptionInformation
[1] = (ULONG
)Cr2
;
163 Er
.NumberParameters
= 0;
167 KiDispatchException(&Er
, 0, Tf
, UserMode
, TRUE
);
172 KiUserTrapHandler(PKTRAP_FRAME Tf
, ULONG ExceptionNr
, PVOID Cr2
)
184 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3
));
187 * Print out the CPU registers
189 if (ExceptionNr
< 19)
191 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings
[ExceptionNr
],
192 ExceptionNr
, Tf
->ErrorCode
&0xffff);
196 DbgPrint("Exception: %d(%x)\n", ExceptionNr
, Tf
->ErrorCode
&0xffff);
198 DbgPrint("CS:EIP %x:%x ", Tf
->Cs
&0xffff, Tf
->Eip
);
199 print_user_address((PVOID
)Tf
->Eip
);
201 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3
));
202 DbgPrint("CR2 %x CR3 %x ", Cr2
, cr3
);
203 DbgPrint("Process: %x ",PsGetCurrentProcess());
204 if (PsGetCurrentProcess() != NULL
)
206 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId
);
207 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName
);
209 if (PsGetCurrentThread() != NULL
)
211 DbgPrint("Thrd: %x Tid: %x",
212 PsGetCurrentThread(),
213 PsGetCurrentThread()->Cid
.UniqueThread
);
216 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf
->Ds
&0xffff, Tf
->Es
&0xffff,
217 Tf
->Fs
&0xffff, Tf
->Gs
&0xfff);
218 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf
->Eax
, Tf
->Ebx
, Tf
->Ecx
);
219 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf
->Edx
, Tf
->Ebp
, Tf
->Esi
);
220 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf
->Edi
, Tf
->Eflags
);
221 DbgPrint("SS:ESP %x:%x\n", Tf
->Ss
, Tf
->Esp
);
224 * Dump the stack frames
226 DbgPrint("Frames: ");
228 Frame
= (PULONG
)Tf
->Ebp
;
229 while (Frame
!= NULL
&& i
< 50)
231 Status
= MmSafeCopyFromUser(&ReturnAddress
, &Frame
[1], sizeof(ULONG
));
232 if (!NT_SUCCESS(Status
))
234 DbgPrint("????????\n");
237 print_user_address((PVOID
)ReturnAddress
);
238 Status
= MmSafeCopyFromUser(&NextFrame
, &Frame
[0], sizeof(ULONG
));
239 if (!NT_SUCCESS(Status
))
241 DbgPrint("Frame is inaccessible.\n");
244 if ((NextFrame
+ sizeof(ULONG
)) >= KERNEL_BASE
)
246 DbgPrint("Next frame is in kernel space!\n");
249 if (NextFrame
!= 0 && NextFrame
<= (ULONG
)Frame
)
251 DbgPrint("Next frame is not above current frame!\n");
254 Frame
= (PULONG
)NextFrame
;
259 * Kill the faulting process
262 ZwTerminateProcess(NtCurrentProcess(), STATUS_NONCONTINUABLE_EXCEPTION
);
265 * If terminating the process fails then bugcheck