[FREELDR] Slightly revamp the Exception BSOD screen.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 1 Jan 2022 03:49:06 +0000 (04:49 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 1 Jan 2022 04:04:23 +0000 (05:04 +0100)
- Don't store trailing newlines in the exception description text strings.
- Remove unused i386PrintChar().
- Display CR4 in x86.

- Use the "indentation" printf generation trick in order to get aligned
  strings for (CF4 and) DR6 and DR7, without having to hardcode the tons
  of alignment whitespaces (--> make the strings stored in freeldr shorter).

- Show the IP/ErrorCode/EFlags/GDTR/IDTR/LDTR values vertically aligned.

- Display the stack frames in both x86 and x64 modes.

- Adjust the instruction pointer when a BREAKPOINT or OVERFLOW exception
  arises, so that the offending instruction can show up in the instruction
  stream.

boot/freeldr/freeldr/arch/i386/i386bug.c
boot/freeldr/freeldr/arch/i386/i386trap.S

index 908ad46..7e03dea 100644 (file)
@@ -5,31 +5,31 @@
 
 typedef struct _FRAME
 {
-    struct _FRAME *Next;
-    void *Address;
+    struct _FRAMENext;
+    PVOID Address;
 } FRAME;
 
 static const CHAR *i386ExceptionDescriptionText[] =
 {
-    "Exception 00: DIVIDE BY ZERO\n\n",
-    "Exception 01: DEBUG EXCEPTION\n\n",
-    "Exception 02: NON-MASKABLE INTERRUPT EXCEPTION\n\n",
-    "Exception 03: BREAKPOINT (INT 3)\n\n",
-    "Exception 04: OVERFLOW\n\n",
-    "Exception 05: BOUND EXCEPTION\n\n",
-    "Exception 06: INVALID OPCODE\n\n",
-    "Exception 07: FPU NOT AVAILABLE\n\n",
-    "Exception 08: DOUBLE FAULT\n\n",
-    "Exception 09: COPROCESSOR SEGMENT OVERRUN\n\n",
-    "Exception 0A: INVALID TSS\n\n",
-    "Exception 0B: SEGMENT NOT PRESENT\n\n",
-    "Exception 0C: STACK EXCEPTION\n\n",
-    "Exception 0D: GENERAL PROTECTION FAULT\n\n",
-    "Exception 0E: PAGE FAULT\n\n",
-    "Exception 0F: Reserved\n\n",
-    "Exception 10: COPROCESSOR ERROR\n\n",
-    "Exception 11: ALIGNMENT CHECK\n\n",
-    "Exception 12: MACHINE CHECK\n\n"
+    "Exception 00: DIVIDE BY ZERO",
+    "Exception 01: DEBUG EXCEPTION",
+    "Exception 02: NON-MASKABLE INTERRUPT EXCEPTION",
+    "Exception 03: BREAKPOINT (INT 3)",
+    "Exception 04: OVERFLOW",
+    "Exception 05: BOUND EXCEPTION",
+    "Exception 06: INVALID OPCODE",
+    "Exception 07: FPU NOT AVAILABLE",
+    "Exception 08: DOUBLE FAULT",
+    "Exception 09: COPROCESSOR SEGMENT OVERRUN",
+    "Exception 0A: INVALID TSS",
+    "Exception 0B: SEGMENT NOT PRESENT",
+    "Exception 0C: STACK EXCEPTION",
+    "Exception 0D: GENERAL PROTECTION FAULT",
+    "Exception 0E: PAGE FAULT",
+    "Exception 0F: Reserved",
+    "Exception 10: COPROCESSOR ERROR",
+    "Exception 11: ALIGNMENT CHECK",
+    "Exception 12: MACHINE CHECK"
 };
 
 #define SCREEN_ATTR 0x1F    // Bright white on blue background
@@ -38,14 +38,6 @@ static const CHAR *i386ExceptionDescriptionText[] =
 static ULONG i386_ScreenPosX = 0;
 static ULONG i386_ScreenPosY = 0;
 
-#if 0
-static void
-i386PrintChar(CHAR chr, ULONG x, ULONG y)
-{
-    MachVideoPutChar(chr, SCREEN_ATTR, x, y);
-}
-#endif
-
 static void
 i386PrintText(CHAR *pszText)
 {
@@ -96,18 +88,17 @@ PrintText(const CHAR *Format, ...)
 static void
 i386PrintFrames(PKTRAP_FRAME TrapFrame)
 {
-    FRAME *Frame;
+    FRAMEFrame;
 
     PrintText("Frames:\n");
+    for (Frame =
 #ifdef _M_IX86
-    for (Frame = (FRAME*)TrapFrame->Ebp;
-         Frame != 0 && (ULONG_PTR)Frame < STACKADDR;
-         Frame = Frame->Next)
+            (FRAME*)TrapFrame->Ebp;
 #else
-    for (Frame = (FRAME*)TrapFrame->TrapFrame;
-         Frame != 0 && (ULONG_PTR)Frame < STACKADDR;
-         Frame = Frame->Next)
+            (FRAME*)TrapFrame->TrapFrame;
 #endif
+         Frame != NULL && (ULONG_PTR)Frame < STACKADDR;
+         Frame = Frame->Next)
     {
         PrintText("%p  ", Frame->Address);
     }
@@ -126,7 +117,8 @@ i386PrintExceptionText(ULONG TrapIndex, PKTRAP_FRAME TrapFrame, PKSPECIAL_REGIST
 
     PrintText("An error occured in " VERSION "\n"
               "Report this error on the ReactOS Bug Tracker: https://jira.reactos.org\n\n"
-              "0x%02lx: %s\n", TrapIndex, i386ExceptionDescriptionText[TrapIndex]);
+              "0x%02lx: %s\n\n", TrapIndex, i386ExceptionDescriptionText[TrapIndex]);
+
 #ifdef _M_IX86
     PrintText("EAX: %.8lx        ESP: %.8lx        CR0: %.8lx        DR0: %.8lx\n",
               TrapFrame->Eax, TrapFrame->HardwareEsp, Special->Cr0, TrapFrame->Dr0);
@@ -136,29 +128,28 @@ i386PrintExceptionText(ULONG TrapIndex, PKTRAP_FRAME TrapFrame, PKSPECIAL_REGIST
               TrapFrame->Ecx, TrapFrame->Esi, Special->Cr2, TrapFrame->Dr2);
     PrintText("EDX: %.8lx        EDI: %.8lx        CR3: %.8lx        DR3: %.8lx\n",
               TrapFrame->Edx, TrapFrame->Edi, Special->Cr3, TrapFrame->Dr3);
-    PrintText("                                                               DR6: %.8lx\n",
-              TrapFrame->Dr6);
-    PrintText("                                                               DR7: %.8lx\n\n",
-              TrapFrame->Dr7);
+    PrintText("%*s CR4: %.8lx        DR6: %.8lx\n",
+              41, "", Special->Cr4, TrapFrame->Dr6);
+    PrintText("%*s DR7: %.8lx\n",
+              62, "", TrapFrame->Dr7);
 
     /* NOTE: Segment registers are intrinsically 16 bits. Even if the x86
      * KTRAP_FRAME structure stores them as ULONG, only their lower 16 bits
      * are initialized. We thus cast them to USHORT before display. */
-    PrintText("CS: %.4lx        EIP: %.8lx\n",
+    PrintText(" CS: %.4lx            EIP: %.8lx\n",
               (USHORT)TrapFrame->SegCs, TrapFrame->Eip);
-    PrintText("DS: %.4lx        ERROR CODE: %.8lx\n",
+    PrintText(" DS: %.4lx     ERROR CODE: %.8lx\n",
               (USHORT)TrapFrame->SegDs, TrapFrame->ErrCode);
-    PrintText("ES: %.4lx        EFLAGS: %.8lx\n",
+    PrintText(" ES: %.4lx         EFLAGS: %.8lx\n",
               (USHORT)TrapFrame->SegEs, TrapFrame->EFlags);
-    PrintText("FS: %.4lx        GDTR Base: %.8lx Limit: %.4x\n",
+    PrintText(" FS: %.4lx      GDTR Base: %.8lx Limit: %.4x\n",
+           // " FS: %.4lx           GDTR: Base %.8lx Limit %.4x\n"
               (USHORT)TrapFrame->SegFs, Special->Gdtr.Base, Special->Gdtr.Limit);
-    PrintText("GS: %.4lx        IDTR Base: %.8lx Limit: %.4x\n",
+    PrintText(" GS: %.4lx      IDTR Base: %.8lx Limit: %.4x\n",
+           // " GS: %.4lx           IDTR: Base %.8lx Limit %.4x\n",
               (USHORT)TrapFrame->SegGs, Special->Idtr.Base, Special->Idtr.Limit);
-    PrintText("SS: %.4lx        LDTR: %.4lx TR: %.4lx\n\n",
+    PrintText(" SS: %.4lx           LDTR: %.4lx TR: %.4lx\n\n",
               (USHORT)TrapFrame->HardwareSegSs, Special->Ldtr, Special->Tr);
-
-    i386PrintFrames(TrapFrame);                        // Display frames
-    InstructionPointer = (PUCHAR)TrapFrame->Eip;
 #else
     PrintText("RAX: %.8lx        R8:  %.8lx        R12: %.8lx        RSI: %.8lx\n",
               TrapFrame->Rax, TrapFrame->R8, 0, TrapFrame->Rsi);
@@ -169,21 +160,33 @@ i386PrintExceptionText(ULONG TrapIndex, PKTRAP_FRAME TrapFrame, PKSPECIAL_REGIST
     PrintText("RDX: %.8lx        R11: %.8lx        R15: %.8lx        RSP: %.8lx\n",
               TrapFrame->Rdx, TrapFrame->R11, 0, TrapFrame->Rsp);
 
-    PrintText("CS: %.4lx        RIP: %.8lx\n",
+    PrintText(" CS: %.4lx            RIP: %.8lx\n",
               TrapFrame->SegCs, TrapFrame->Rip);
-    PrintText("DS: %.4lx        ERROR CODE: %.8lx\n",
+    PrintText(" DS: %.4lx     ERROR CODE: %.8lx\n",
               TrapFrame->SegDs, TrapFrame->ErrorCode);
-    PrintText("ES: %.4lx        EFLAGS: %.8lx\n",
+    PrintText(" ES: %.4lx         EFLAGS: %.8lx\n",
               TrapFrame->SegEs, TrapFrame->EFlags);
-    PrintText("FS: %.4lx        GDTR Base: %.8lx Limit: %.4x\n",
+    PrintText(" FS: %.4lx      GDTR Base: %.8lx Limit: %.4x\n",
               TrapFrame->SegFs, Special->Gdtr.Base, Special->Gdtr.Limit);
-    PrintText("GS: %.4lx        IDTR Base: %.8lx Limit: %.4x\n",
+    PrintText(" GS: %.4lx      IDTR Base: %.8lx Limit: %.4x\n",
               TrapFrame->SegGs, Special->Idtr.Base, Special->Idtr.Limit);
-    PrintText("SS: %.4lx        LDTR: %.4lx TR: %.4lx\n\n",
+    PrintText(" SS: %.4lx           LDTR: %.4lx TR: %.4lx\n\n",
               TrapFrame->SegSs, Special->Ldtr, Special->Tr);
+#endif
+
+    /* Display the stack frames */
+    i386PrintFrames(TrapFrame);
+
+#ifdef _M_IX86
+    InstructionPointer = (PUCHAR)TrapFrame->Eip;
+#else
     InstructionPointer = (PUCHAR)TrapFrame->Rip;
 #endif
-    PrintText("\nInstruction stream: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x \n",
+    /* Adjust IP for #BP (INT 03) or #OF to point to the offending instruction */
+    if ((TrapIndex == 3) || (TrapIndex == 4))
+        InstructionPointer--;
+
+    PrintText("\nInstruction stream: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
               InstructionPointer[0], InstructionPointer[1],
               InstructionPointer[2], InstructionPointer[3],
               InstructionPointer[4], InstructionPointer[5],
index 0be6ec7..bbc5367 100644 (file)
@@ -82,7 +82,7 @@ MACRO(SAVE_CPU_REGS)
     push eax
 ENDM
 
-/* Set by each exception handler to the address of the description text */
+/* Set by each exception handler to the index of the description text */
 i386ExceptionIndex:
     .long   0