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