Fixed null pointer exceptions.
[reactos.git] / reactos / ntoskrnl / ke / i386 / usertrap.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/i386/usertrap.c
22 * PURPOSE: Handling usermode exceptions.
23 * PROGRAMMER: David Welch (welch@cwcom.net)
24 * REVISION HISTORY:
25 * 18/11/01: Split from ntoskrnl/ke/i386/exp.c
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <roscfg.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>
42
43 #define NDEBUG
44 #include <internal/debug.h>
45
46 /* GLOBALS *****************************************************************/
47
48 static char *ExceptionTypeStrings[] =
49 {
50 "Divide Error",
51 "Debug Trap",
52 "NMI",
53 "Breakpoint",
54 "Overflow",
55 "BOUND range exceeded",
56 "Invalid Opcode",
57 "No Math Coprocessor",
58 "Double Fault",
59 "Unknown(9)",
60 "Invalid TSS",
61 "Segment Not Present",
62 "Stack Segment Fault",
63 "General Protection",
64 "Page Fault",
65 "Math Fault",
66 "Alignment Check",
67 "Machine Check"
68 };
69
70 /* FUNCTIONS ****************************************************************/
71
72 STATIC BOOLEAN
73 print_user_address(PVOID address)
74 {
75 PLIST_ENTRY current_entry;
76 PLDR_MODULE current;
77 PEPROCESS CurrentProcess;
78 PPEB Peb = NULL;
79 ULONG_PTR RelativeAddress;
80
81 CurrentProcess = PsGetCurrentProcess();
82 if (NULL != CurrentProcess)
83 {
84 Peb = CurrentProcess->Peb;
85 }
86
87 if (NULL == Peb)
88 {
89 DbgPrint("<%x>", address);
90 return(TRUE);
91 }
92
93 current_entry = Peb->Ldr->InLoadOrderModuleList.Flink;
94
95 while (current_entry != &Peb->Ldr->InLoadOrderModuleList &&
96 current_entry != NULL)
97 {
98 current =
99 CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList);
100
101 if (address >= (PVOID)current->BaseAddress &&
102 address < (PVOID)(current->BaseAddress + current->SizeOfImage))
103 {
104 RelativeAddress =
105 (ULONG_PTR) address - (ULONG_PTR)current->BaseAddress;
106 DbgPrint("<%wZ: %x>", &current->BaseDllName, RelativeAddress);
107 return(TRUE);
108 }
109
110 current_entry = current_entry->Flink;
111 }
112 return(FALSE);
113 }
114
115 #if 0
116 /*
117 * Disabled until SEH support is implemented.
118 */
119 ULONG
120 KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
121 {
122 EXCEPTION_RECORD Er;
123
124 if (ExceptionNr == 0)
125 {
126 Er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
127 }
128 else if (ExceptionNr == 1)
129 {
130 Er.ExceptionCode = STATUS_SINGLE_STEP;
131 }
132 else if (ExceptionNr == 3)
133 {
134 Er.ExceptionCode = STATUS_BREAKPOINT;
135 }
136 else if (ExceptionNr == 4)
137 {
138 Er.ExceptionCode = STATUS_INTEGER_OVERFLOW;
139 }
140 else if (ExceptionNr == 5)
141 {
142 Er.ExceptionCode = STATUS_ARRAY_BOUNDS_EXCEEDED;
143 }
144 else if (ExceptionNr == 6)
145 {
146 Er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
147 }
148 else
149 {
150 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
151 }
152 Er.ExceptionFlags = 0;
153 Er.ExceptionRecord = NULL;
154 Er.ExceptionAddress = (PVOID)Tf->Eip;
155 if (ExceptionNr == 14)
156 {
157 Er.NumberParameters = 2;
158 Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
159 Er.ExceptionInformation[1] = (ULONG)Cr2;
160 }
161 else
162 {
163 Er.NumberParameters = 0;
164 }
165
166
167 KiDispatchException(&Er, 0, Tf, UserMode, TRUE);
168 return(0);
169 }
170 #else
171 ULONG
172 KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
173 {
174 PULONG Frame;
175 ULONG cr3;
176 ULONG i;
177 ULONG ReturnAddress;
178 ULONG NextFrame;
179 NTSTATUS Status;
180
181 /*
182 * Get the PDBR
183 */
184 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
185
186 /*
187 * Print out the CPU registers
188 */
189 if (ExceptionNr < 19)
190 {
191 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
192 ExceptionNr, Tf->ErrorCode&0xffff);
193 }
194 else
195 {
196 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
197 }
198 DbgPrint("CS:EIP %x:%x ", Tf->Cs&0xffff, Tf->Eip);
199 print_user_address((PVOID)Tf->Eip);
200 DbgPrint("\n");
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)
205 {
206 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
207 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
208 }
209 if (PsGetCurrentThread() != NULL)
210 {
211 DbgPrint("Thrd: %x Tid: %x",
212 PsGetCurrentThread(),
213 PsGetCurrentThread()->Cid.UniqueThread);
214 }
215 DbgPrint("\n");
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);
222
223 /*
224 * Dump the stack frames
225 */
226 DbgPrint("Frames: ");
227 i = 1;
228 Frame = (PULONG)Tf->Ebp;
229 while (Frame != NULL && i < 50)
230 {
231 Status = MmSafeCopyFromUser(&ReturnAddress, &Frame[1], sizeof(ULONG));
232 if (!NT_SUCCESS(Status))
233 {
234 DbgPrint("????????\n");
235 break;
236 }
237 print_user_address((PVOID)ReturnAddress);
238 Status = MmSafeCopyFromUser(&NextFrame, &Frame[0], sizeof(ULONG));
239 if (!NT_SUCCESS(Status))
240 {
241 DbgPrint("Frame is inaccessible.\n");
242 break;
243 }
244 if ((NextFrame + sizeof(ULONG)) >= KERNEL_BASE)
245 {
246 DbgPrint("Next frame is in kernel space!\n");
247 break;
248 }
249 if (NextFrame != 0 && NextFrame <= (ULONG)Frame)
250 {
251 DbgPrint("Next frame is not above current frame!\n");
252 break;
253 }
254 Frame = (PULONG)NextFrame;
255 i++;
256 }
257
258 /*
259 * Kill the faulting process
260 */
261 __asm__("sti\n\t");
262 ZwTerminateProcess(NtCurrentProcess(), STATUS_NONCONTINUABLE_EXCEPTION);
263
264 /*
265 * If terminating the process fails then bugcheck
266 */
267 KeBugCheck(0);
268 return(0);
269 }
270 #endif