MiQueryVirtualMemory(): created because ZwQueryVirtualMemory() didn't work for me...
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.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/exp.c
22 * PURPOSE: Handling exceptions
23 * PROGRAMMERS: David Welch (welch@cwcom.net)
24 * Skywing (skywing@valhallalegends.com)
25 * REVISION HISTORY:
26 * ??/??/??: Created
27 * 09/12/03: KeRaiseUserException added (Skywing).
28 */
29
30 /* INCLUDES *****************************************************************/
31
32 #include <ntoskrnl.h>
33 #include <pseh.h>
34 #define NDEBUG
35 #include <internal/debug.h>
36
37 /* GLOBALS *****************************************************************/
38
39 #define FLAG_IF (1<<9)
40
41 #define _STR(x) #x
42 #define STR(x) _STR(x)
43
44 #ifndef ARRAY_SIZE
45 # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
46 #endif
47
48 extern void interrupt_handler2e(void);
49 extern void interrupt_handler2d(void);
50
51 extern VOID KiTrap0(VOID);
52 extern VOID KiTrap1(VOID);
53 extern VOID KiTrap2(VOID);
54 extern VOID KiTrap3(VOID);
55 extern VOID KiTrap4(VOID);
56 extern VOID KiTrap5(VOID);
57 extern VOID KiTrap6(VOID);
58 extern VOID KiTrap7(VOID);
59 extern VOID KiTrap8(VOID);
60 extern VOID KiTrap9(VOID);
61 extern VOID KiTrap10(VOID);
62 extern VOID KiTrap11(VOID);
63 extern VOID KiTrap12(VOID);
64 extern VOID KiTrap13(VOID);
65 extern VOID KiTrap14(VOID);
66 extern VOID KiTrap15(VOID);
67 extern VOID KiTrap16(VOID);
68 extern VOID KiTrap17(VOID);
69 extern VOID KiTrap18(VOID);
70 extern VOID KiTrap19(VOID);
71 extern VOID KiTrapUnknown(VOID);
72
73 extern ULONG init_stack;
74 extern ULONG init_stack_top;
75
76 extern BOOLEAN Ke386NoExecute;
77
78 static char *ExceptionTypeStrings[] =
79 {
80 "Divide Error",
81 "Debug Trap",
82 "NMI",
83 "Breakpoint",
84 "Overflow",
85 "BOUND range exceeded",
86 "Invalid Opcode",
87 "No Math Coprocessor",
88 "Double Fault",
89 "Unknown(9)",
90 "Invalid TSS",
91 "Segment Not Present",
92 "Stack Segment Fault",
93 "General Protection",
94 "Page Fault",
95 "Reserved(15)",
96 "Math Fault",
97 "Alignment Check",
98 "Machine Check",
99 "SIMD Fault"
100 };
101
102 static NTSTATUS ExceptionToNtStatus[] =
103 {
104 STATUS_INTEGER_DIVIDE_BY_ZERO,
105 STATUS_SINGLE_STEP,
106 STATUS_ACCESS_VIOLATION,
107 STATUS_BREAKPOINT,
108 STATUS_INTEGER_OVERFLOW,
109 STATUS_ARRAY_BOUNDS_EXCEEDED,
110 STATUS_ILLEGAL_INSTRUCTION,
111 STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
112 STATUS_ACCESS_VIOLATION,
113 STATUS_ACCESS_VIOLATION,
114 STATUS_ACCESS_VIOLATION,
115 STATUS_ACCESS_VIOLATION,
116 STATUS_STACK_OVERFLOW,
117 STATUS_ACCESS_VIOLATION,
118 STATUS_ACCESS_VIOLATION,
119 STATUS_ACCESS_VIOLATION, /* RESERVED */
120 STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
121 STATUS_DATATYPE_MISALIGNMENT,
122 STATUS_ACCESS_VIOLATION,
123 STATUS_ACCESS_VIOLATION /* STATUS_FLT_MULTIPLE_TRAPS? */
124 };
125
126 /* FUNCTIONS ****************************************************************/
127
128 #if defined(DBG) || defined(KDBG)
129 BOOLEAN STDCALL
130 KeRosPrintAddress(PVOID address)
131 {
132 return KdbSymPrintAddress(address);
133 }
134 #else /* KDBG */
135 BOOLEAN STDCALL
136 KeRosPrintAddress(PVOID address)
137 {
138 PLIST_ENTRY current_entry;
139 MODULE_TEXT_SECTION* current;
140 extern LIST_ENTRY ModuleTextListHead;
141 ULONG_PTR RelativeAddress;
142
143 current_entry = ModuleTextListHead.Flink;
144
145 while (current_entry != &ModuleTextListHead &&
146 current_entry != NULL)
147 {
148 current =
149 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
150
151 if (address >= (PVOID)current->Base &&
152 address < (PVOID)(current->Base + current->Length))
153 {
154 RelativeAddress = (ULONG_PTR) address - current->Base;
155 DbgPrint("<%ws: %x>", current->Name, RelativeAddress);
156 return(TRUE);
157 }
158 current_entry = current_entry->Flink;
159 }
160 return(FALSE);
161 }
162 #endif /* KDBG */
163
164 ULONG
165 KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
166 {
167 EXCEPTION_RECORD Er;
168
169 Er.ExceptionFlags = 0;
170 Er.ExceptionRecord = NULL;
171 Er.ExceptionAddress = (PVOID)Tf->Eip;
172
173 if (ExceptionNr == 14)
174 {
175 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
176 Er.NumberParameters = 2;
177 Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
178 Er.ExceptionInformation[1] = (ULONG)Cr2;
179 }
180 else
181 {
182 if (ExceptionNr < ARRAY_SIZE(ExceptionToNtStatus))
183 {
184 Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
185 }
186 else
187 {
188 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
189 }
190 Er.NumberParameters = 0;
191 }
192
193 Er.ExceptionFlags = ((NTSTATUS) STATUS_SINGLE_STEP == (NTSTATUS) Er.ExceptionCode
194 || (NTSTATUS) STATUS_BREAKPOINT == (NTSTATUS) Er.ExceptionCode) ?
195 EXCEPTION_NONCONTINUABLE : 0;
196
197 KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
198
199 return(0);
200 }
201
202 ULONG
203 KiDoubleFaultHandler(VOID)
204 {
205 unsigned int cr2;
206 ULONG StackLimit;
207 ULONG StackBase;
208 ULONG Esp0;
209 ULONG ExceptionNr = 8;
210 KTSS* OldTss;
211 PULONG Frame;
212 ULONG OldCr3;
213 #if 0
214 ULONG i, j;
215 static PVOID StackTrace[MM_STACK_SIZE / sizeof(PVOID)];
216 static ULONG StackRepeatCount[MM_STACK_SIZE / sizeof(PVOID)];
217 static ULONG StackRepeatLength[MM_STACK_SIZE / sizeof(PVOID)];
218 ULONG TraceLength;
219 BOOLEAN FoundRepeat;
220 #endif
221
222 OldTss = KeGetCurrentKPCR()->TSS;
223 Esp0 = OldTss->Esp;
224
225 /* Get CR2 */
226 cr2 = Ke386GetCr2();
227 if (PsGetCurrentThread() != NULL &&
228 PsGetCurrentThread()->ThreadsProcess != NULL)
229 {
230 OldCr3 = (ULONG)
231 PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart;
232 }
233 else
234 {
235 OldCr3 = 0xBEADF0AL;
236 }
237
238 /*
239 * Check for stack underflow
240 */
241 if (PsGetCurrentThread() != NULL &&
242 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
243 {
244 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
245 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
246 ExceptionNr = 12;
247 }
248
249 /*
250 * Print out the CPU registers
251 */
252 if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
253 {
254 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
255 ExceptionNr, 0);
256 }
257 else
258 {
259 DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
260 }
261 DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
262 KeRosPrintAddress((PVOID)OldTss->Eip);
263 DbgPrint("\n");
264 DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
265 DbgPrint("Proc: %x ",PsGetCurrentProcess());
266 if (PsGetCurrentProcess() != NULL)
267 {
268 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
269 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
270 }
271 if (PsGetCurrentThread() != NULL)
272 {
273 DbgPrint("Thrd: %x Tid: %x",
274 PsGetCurrentThread(),
275 PsGetCurrentThread()->Cid.UniqueThread);
276 }
277 DbgPrint("\n");
278 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es,
279 OldTss->Fs, OldTss->Gs);
280 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
281 OldTss->Ecx);
282 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n ESP: %.8x", OldTss->Edx,
283 OldTss->Ebp, OldTss->Esi, Esp0);
284 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
285 if (OldTss->Cs == KERNEL_CS)
286 {
287 DbgPrint("kESP %.8x ", Esp0);
288 if (PsGetCurrentThread() != NULL)
289 {
290 DbgPrint("kernel stack base %x\n",
291 PsGetCurrentThread()->Tcb.StackLimit);
292
293 }
294 }
295 else
296 {
297 DbgPrint("User ESP %.8x\n", OldTss->Esp);
298 }
299 if ((OldTss->Cs & 0xffff) == KERNEL_CS)
300 {
301 if (PsGetCurrentThread() != NULL)
302 {
303 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
304 StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit;
305 }
306 else
307 {
308 StackLimit = (ULONG)&init_stack_top;
309 StackBase = (ULONG)&init_stack;
310 }
311
312 /*
313 Change to an #if 0 to reduce the amount of information printed on
314 a recursive stack trace.
315 */
316 #if 1
317 DbgPrint("Frames: ");
318 Frame = (PULONG)OldTss->Ebp;
319 while (Frame != NULL && (ULONG)Frame >= StackBase)
320 {
321 KeRosPrintAddress((PVOID)Frame[1]);
322 Frame = (PULONG)Frame[0];
323 DbgPrint(" ");
324 }
325 #else
326 DbgPrint("Frames: ");
327 i = 0;
328 Frame = (PULONG)OldTss->Ebp;
329 while (Frame != NULL && (ULONG)Frame >= StackBase)
330 {
331 StackTrace[i] = (PVOID)Frame[1];
332 Frame = (PULONG)Frame[0];
333 i++;
334 }
335 TraceLength = i;
336
337 i = 0;
338 while (i < TraceLength)
339 {
340 StackRepeatCount[i] = 0;
341 j = i + 1;
342 FoundRepeat = FALSE;
343 while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE)
344 {
345 if (memcmp(&StackTrace[i], &StackTrace[j],
346 (j - i) * sizeof(PVOID)) == 0)
347 {
348 StackRepeatCount[i] = 2;
349 StackRepeatLength[i] = j - i;
350 FoundRepeat = TRUE;
351 }
352 else
353 {
354 j++;
355 }
356 }
357 if (FoundRepeat == FALSE)
358 {
359 i++;
360 continue;
361 }
362 j = j + StackRepeatLength[i];
363 while ((TraceLength - j) >= StackRepeatLength[i] &&
364 FoundRepeat == TRUE)
365 {
366 if (memcmp(&StackTrace[i], &StackTrace[j],
367 StackRepeatLength[i] * sizeof(PVOID)) == 0)
368 {
369 StackRepeatCount[i]++;
370 j = j + StackRepeatLength[i];
371 }
372 else
373 {
374 FoundRepeat = FALSE;
375 }
376 }
377 i = j;
378 }
379
380 i = 0;
381 while (i < TraceLength)
382 {
383 if (StackRepeatCount[i] == 0)
384 {
385 KeRosPrintAddress(StackTrace[i]);
386 i++;
387 }
388 else
389 {
390 DbgPrint("{");
391 if (StackRepeatLength[i] == 0)
392 {
393 for(;;);
394 }
395 for (j = 0; j < StackRepeatLength[i]; j++)
396 {
397 KeRosPrintAddress(StackTrace[i + j]);
398 }
399 DbgPrint("}*%d", StackRepeatCount[i]);
400 i = i + StackRepeatLength[i] * StackRepeatCount[i];
401 }
402 }
403 #endif
404 }
405
406 DbgPrint("\n");
407 for(;;);
408 return 0;
409 }
410
411 VOID
412 KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
413 {
414 ULONG cr3_;
415 ULONG i;
416 ULONG StackLimit;
417 PULONG Frame;
418 ULONG Esp0;
419 ULONG ExceptionNr = (ULONG)Tf->DebugArgMark;
420 ULONG cr2 = (ULONG)Tf->DebugPointer;
421
422 Esp0 = (ULONG)Tf;
423
424 /*
425 * Print out the CPU registers
426 */
427 if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
428 {
429 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
430 ExceptionNr, Tf->ErrorCode&0xffff);
431 }
432 else
433 {
434 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
435 }
436 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
437 Tf->Cs&0xffff, Tf->Eip);
438 KeRosPrintAddress((PVOID)Tf->Eip);
439 DbgPrint("\n");
440 Ke386GetPageTableDirectory(cr3_);
441 DbgPrint("cr2 %x cr3 %x ", cr2, cr3_);
442 DbgPrint("Proc: %x ",PsGetCurrentProcess());
443 if (PsGetCurrentProcess() != NULL)
444 {
445 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
446 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
447 }
448 if (PsGetCurrentThread() != NULL)
449 {
450 DbgPrint("Thrd: %x Tid: %x",
451 PsGetCurrentThread(),
452 PsGetCurrentThread()->Cid.UniqueThread);
453 }
454 DbgPrint("\n");
455 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
456 Tf->Fs&0xffff, Tf->Gs&0xfff);
457 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
458 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf->Edx,
459 Tf->Ebp, Tf->Esi, Esp0);
460 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
461 if ((Tf->Cs&0xffff) == KERNEL_CS)
462 {
463 DbgPrint("kESP %.8x ", Esp0);
464 if (PsGetCurrentThread() != NULL)
465 {
466 DbgPrint("kernel stack base %x\n",
467 PsGetCurrentThread()->Tcb.StackLimit);
468
469 }
470 }
471
472 if (PsGetCurrentThread() != NULL)
473 {
474 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
475 }
476 else
477 {
478 StackLimit = (ULONG)&init_stack_top;
479 }
480
481 /*
482 * Dump the stack frames
483 */
484 DbgPrint("Frames: ");
485 /* Change to an #if 0 if no frames are printed because of fpo. */
486 #if 1
487 i = 1;
488 Frame = (PULONG)Tf->Ebp;
489 while (Frame != NULL)
490 {
491 NTSTATUS Status;
492 PVOID Eip;
493 Status = MmSafeCopyFromUser(&Eip, Frame + 1, sizeof(Eip));
494 if (!NT_SUCCESS(Status))
495 {
496 DbgPrint("<INVALID>");
497 break;
498 }
499 if (!KeRosPrintAddress(Eip))
500 {
501 DbgPrint("<%X>", Eip);
502 }
503 Status = MmSafeCopyFromUser(&Frame, Frame, sizeof(Frame));
504 if (!NT_SUCCESS(Status))
505 {
506 break;
507 }
508 i++;
509 DbgPrint(" ");
510 }
511 #else
512 i = 1;
513 Frame = (PULONG)((ULONG_PTR)Esp0 + KTRAP_FRAME_EFLAGS);
514 while (Frame < (PULONG)PsGetCurrentThread()->Tcb.StackBase && i < 50)
515 {
516 ULONG Address = *Frame;
517 if (KeRosPrintAddress((PVOID)Address))
518 {
519 i++;
520 }
521 Frame++;
522 }
523 #endif
524 }
525
526 ULONG
527 KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
528 /*
529 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
530 * message and halt the computer
531 * ARGUMENTS:
532 * Complete CPU context
533 */
534 {
535 unsigned int cr2;
536 NTSTATUS Status;
537 ULONG Esp0;
538
539 /* Store the exception number in an unused field in the trap frame. */
540 Tf->DebugArgMark = (PVOID)ExceptionNr;
541
542 /* Use the address of the trap frame as approximation to the ring0 esp */
543 Esp0 = (ULONG)&Tf->Eip;
544
545 /* Get CR2 */
546 cr2 = Ke386GetCr2();
547 Tf->DebugPointer = (PVOID)cr2;
548
549 if (ExceptionNr == 14 && Tf->Eflags & FLAG_IF)
550 {
551 Ke386EnableInterrupts();
552 }
553
554 /*
555 * If this was a V86 mode exception then handle it specially
556 */
557 if (Tf->Eflags & (1 << 17))
558 {
559 return(KeV86Exception(ExceptionNr, Tf, cr2));
560 }
561
562 /*
563 * Check for stack underflow, this may be obsolete
564 */
565 if (PsGetCurrentThread() != NULL &&
566 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
567 {
568 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
569 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
570 ExceptionNr = 12;
571 }
572
573 /*
574 * Maybe handle the page fault and return
575 */
576 if (ExceptionNr == 14)
577 {
578 if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2 >= KERNEL_BASE)
579 {
580 KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
581 }
582 Status = MmPageFault(Tf->Cs&0xffff,
583 &Tf->Eip,
584 &Tf->Eax,
585 cr2,
586 Tf->ErrorCode);
587 if (NT_SUCCESS(Status))
588 {
589 return(0);
590 }
591 }
592
593 /*
594 * Check for a breakpoint that was only for the attention of the debugger.
595 */
596 if (ExceptionNr == 3 && Tf->Eip == ((ULONG)DbgBreakPointNoBugCheck) + 1)
597 {
598 /*
599 EIP is already adjusted by the processor to point to the instruction
600 after the breakpoint.
601 */
602 return(0);
603 }
604
605 /*
606 * Try to handle device-not-present, math-fault and xmm-fault exceptions.
607 */
608 if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
609 {
610 Status = KiHandleFpuFault(Tf, ExceptionNr);
611 if (NT_SUCCESS(Status))
612 {
613 return(0);
614 }
615 }
616
617 /*
618 * Handle user exceptions differently
619 */
620 if ((Tf->Cs & 0xFFFF) == USER_CS)
621 {
622 return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
623 }
624 else
625 {
626 return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
627 }
628 }
629
630 VOID
631 KeDumpStackFrames(PULONG Frame)
632 {
633 PULONG StackBase, StackEnd;
634 MEMORY_BASIC_INFORMATION mbi;
635 ULONG ResultLength = sizeof(mbi);
636 NTSTATUS Status;
637
638 DbgPrint("Frames: ");
639 _SEH_TRY
640 {
641 Status = MiQueryVirtualMemory (
642 (HANDLE)-1,
643 Frame,
644 MemoryBasicInformation,
645 &mbi,
646 sizeof(mbi),
647 &ResultLength );
648 if ( !NT_SUCCESS(Status) )
649 {
650 DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
651 return;
652 }
653
654 StackBase = Frame;
655 StackEnd = mbi.BaseAddress + mbi.RegionSize;
656
657 while ( Frame >= StackBase && Frame < StackEnd )
658 {
659 ULONG Addr = Frame[1];
660 if (!KeRosPrintAddress((PVOID)Addr))
661 DbgPrint("<%X>", Addr);
662 if ( Addr == 0 || Addr == 0xDEADBEEF )
663 break;
664 StackBase = Frame;
665 Frame = (PULONG)Frame[0];
666 DbgPrint(" ");
667 }
668 }
669 _SEH_HANDLE
670 {
671 }
672 _SEH_END;
673 DbgPrint("\n");
674 }
675
676 VOID STDCALL
677 KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
678 {
679 ULONG i=0;
680 PULONG StackBase, StackEnd;
681 MEMORY_BASIC_INFORMATION mbi;
682 ULONG ResultLength = sizeof(mbi);
683 NTSTATUS Status;
684
685 DbgPrint("Frames: ");
686 _SEH_TRY
687 {
688 if ( !Frame )
689 {
690 #if defined __GNUC__
691 __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
692 #elif defined(_MSC_VER)
693 __asm mov [Frame], ebp
694 #endif
695 //Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
696 }
697
698 Status = MiQueryVirtualMemory (
699 (HANDLE)-1,
700 Frame,
701 MemoryBasicInformation,
702 &mbi,
703 sizeof(mbi),
704 &ResultLength );
705 if ( !NT_SUCCESS(Status) )
706 {
707 DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
708 return;
709 }
710
711 StackBase = Frame;
712 StackEnd = mbi.BaseAddress + mbi.RegionSize;
713
714 while ( Frame >= StackBase && Frame < StackEnd && i++ < FrameCount )
715 {
716 ULONG Addr = Frame[1];
717 if (!KeRosPrintAddress((PVOID)Addr))
718 DbgPrint("<%X>", Addr);
719 if ( Addr == 0 || Addr == 0xDEADBEEF )
720 break;
721 StackBase = Frame;
722 Frame = (PULONG)Frame[0];
723 DbgPrint(" ");
724 }
725 }
726 _SEH_HANDLE
727 {
728 }
729 _SEH_END;
730 DbgPrint("\n");
731 }
732
733 ULONG STDCALL
734 KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
735 {
736 ULONG Count = 0;
737 PULONG StackBase, StackEnd, Frame;
738 MEMORY_BASIC_INFORMATION mbi;
739 ULONG ResultLength = sizeof(mbi);
740 NTSTATUS Status;
741
742 _SEH_TRY
743 {
744 #if defined __GNUC__
745 __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
746 #elif defined(_MSC_VER)
747 __asm mov [Frame], ebp
748 #endif
749
750 Status = MiQueryVirtualMemory (
751 (HANDLE)-1,
752 Frame,
753 MemoryBasicInformation,
754 &mbi,
755 sizeof(mbi),
756 &ResultLength );
757 if ( !NT_SUCCESS(Status) )
758 {
759 DPRINT1("Can't get stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
760 return 0;
761 }
762
763 StackBase = Frame;
764 StackEnd = mbi.BaseAddress + mbi.RegionSize;
765
766 while ( Count < FrameCount && Frame >= StackBase && Frame < StackEnd )
767 {
768 Frames[Count++] = Frame[1];
769 StackBase = Frame;
770 Frame = (PULONG)Frame[0];
771 }
772 }
773 _SEH_HANDLE
774 {
775 }
776 _SEH_END;
777 return Count;
778 }
779
780 static void
781 set_system_call_gate(unsigned int sel, unsigned int func)
782 {
783 DPRINT("sel %x %d\n",sel,sel);
784 KiIdt[sel].a = (((int)func)&0xffff) +
785 (KERNEL_CS << 16);
786 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
787 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
788 }
789
790 static void set_interrupt_gate(unsigned int sel, unsigned int func)
791 {
792 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
793 KiIdt[sel].a = (((int)func)&0xffff) +
794 (KERNEL_CS << 16);
795 KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
796 }
797
798 static void set_trap_gate(unsigned int sel, unsigned int func, unsigned int dpl)
799 {
800 DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel, func, dpl);
801 ASSERT(dpl <= 3);
802 KiIdt[sel].a = (((int)func)&0xffff) +
803 (KERNEL_CS << 16);
804 KiIdt[sel].b = 0x8f00 + (dpl << 13) + (((int)func)&0xffff0000);
805 }
806
807 static void
808 set_task_gate(unsigned int sel, unsigned task_sel)
809 {
810 KiIdt[sel].a = task_sel << 16;
811 KiIdt[sel].b = 0x8500;
812 }
813
814 VOID INIT_FUNCTION
815 KeInitExceptions(VOID)
816 /*
817 * FUNCTION: Initalize CPU exception handling
818 */
819 {
820 int i;
821
822 DPRINT("KeInitExceptions()\n");
823
824 /*
825 * Set up the other gates
826 */
827 set_trap_gate(0, (ULONG)KiTrap0, 0);
828 set_trap_gate(1, (ULONG)KiTrap1, 0);
829 set_trap_gate(2, (ULONG)KiTrap2, 0);
830 set_trap_gate(3, (ULONG)KiTrap3, 3);
831 set_trap_gate(4, (ULONG)KiTrap4, 0);
832 set_trap_gate(5, (ULONG)KiTrap5, 0);
833 set_trap_gate(6, (ULONG)KiTrap6, 0);
834 set_trap_gate(7, (ULONG)KiTrap7, 0);
835 set_task_gate(8, TRAP_TSS_SELECTOR);
836 set_trap_gate(9, (ULONG)KiTrap9, 0);
837 set_trap_gate(10, (ULONG)KiTrap10, 0);
838 set_trap_gate(11, (ULONG)KiTrap11, 0);
839 set_trap_gate(12, (ULONG)KiTrap12, 0);
840 set_trap_gate(13, (ULONG)KiTrap13, 0);
841 set_interrupt_gate(14, (ULONG)KiTrap14);
842 set_trap_gate(15, (ULONG)KiTrap15, 0);
843 set_trap_gate(16, (ULONG)KiTrap16, 0);
844 set_trap_gate(17, (ULONG)KiTrap17, 0);
845 set_trap_gate(18, (ULONG)KiTrap18, 0);
846 set_trap_gate(19, (ULONG)KiTrap19, 0);
847
848 for (i = 20; i < 256; i++)
849 {
850 set_trap_gate(i,(int)KiTrapUnknown, 0);
851 }
852
853 set_system_call_gate(0x2d,(int)interrupt_handler2d);
854 set_system_call_gate(0x2e,(int)interrupt_handler2e);
855 }
856
857 /*
858 * @implemented
859 */
860
861 NTSTATUS STDCALL
862 KeRaiseUserException(IN NTSTATUS ExceptionCode)
863 {
864 /* FIXME: This needs SEH */
865 ULONG OldEip;
866 PKTHREAD Thread = KeGetCurrentThread();
867
868 ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */
869 OldEip = Thread->TrapFrame->Eip;
870 Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
871 Thread->Teb->ExceptionCode = ExceptionCode;
872 return((NTSTATUS)OldEip);
873 }
874
875 VOID
876 FASTCALL
877 KeRosTrapReturn ( PKTRAP_FRAME TrapFrame, PKTRAP_FRAME PrevTrapFrame );
878
879 /*
880 * @implemented
881 */
882 NTSTATUS STDCALL
883 NtRaiseException (
884 IN PEXCEPTION_RECORD ExceptionRecord,
885 IN PCONTEXT Context,
886 IN BOOLEAN SearchFrames)
887 {
888 PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame;
889 PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
890
891 KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList;
892
893 KiDispatchException(ExceptionRecord,
894 Context,
895 PsGetCurrentThread()->Tcb.TrapFrame,
896 (KPROCESSOR_MODE)ExGetPreviousMode(),
897 SearchFrames);
898
899 KeRosTrapReturn ( TrapFrame, PrevTrapFrame );
900 return(STATUS_SUCCESS);
901 }