[FREELDR] Slightly revamp the Exception BSOD screen.

- 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.
This commit is contained in:
Hermès Bélusca-Maïto 2022-01-01 04:49:06 +01:00
parent 2c9dbacebb
commit 0d00a5d6eb
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 61 additions and 58 deletions

View file

@ -5,31 +5,31 @@
typedef struct _FRAME typedef struct _FRAME
{ {
struct _FRAME *Next; struct _FRAME* Next;
void *Address; PVOID Address;
} FRAME; } FRAME;
static const CHAR *i386ExceptionDescriptionText[] = static const CHAR *i386ExceptionDescriptionText[] =
{ {
"Exception 00: DIVIDE BY ZERO\n\n", "Exception 00: DIVIDE BY ZERO",
"Exception 01: DEBUG EXCEPTION\n\n", "Exception 01: DEBUG EXCEPTION",
"Exception 02: NON-MASKABLE INTERRUPT EXCEPTION\n\n", "Exception 02: NON-MASKABLE INTERRUPT EXCEPTION",
"Exception 03: BREAKPOINT (INT 3)\n\n", "Exception 03: BREAKPOINT (INT 3)",
"Exception 04: OVERFLOW\n\n", "Exception 04: OVERFLOW",
"Exception 05: BOUND EXCEPTION\n\n", "Exception 05: BOUND EXCEPTION",
"Exception 06: INVALID OPCODE\n\n", "Exception 06: INVALID OPCODE",
"Exception 07: FPU NOT AVAILABLE\n\n", "Exception 07: FPU NOT AVAILABLE",
"Exception 08: DOUBLE FAULT\n\n", "Exception 08: DOUBLE FAULT",
"Exception 09: COPROCESSOR SEGMENT OVERRUN\n\n", "Exception 09: COPROCESSOR SEGMENT OVERRUN",
"Exception 0A: INVALID TSS\n\n", "Exception 0A: INVALID TSS",
"Exception 0B: SEGMENT NOT PRESENT\n\n", "Exception 0B: SEGMENT NOT PRESENT",
"Exception 0C: STACK EXCEPTION\n\n", "Exception 0C: STACK EXCEPTION",
"Exception 0D: GENERAL PROTECTION FAULT\n\n", "Exception 0D: GENERAL PROTECTION FAULT",
"Exception 0E: PAGE FAULT\n\n", "Exception 0E: PAGE FAULT",
"Exception 0F: Reserved\n\n", "Exception 0F: Reserved",
"Exception 10: COPROCESSOR ERROR\n\n", "Exception 10: COPROCESSOR ERROR",
"Exception 11: ALIGNMENT CHECK\n\n", "Exception 11: ALIGNMENT CHECK",
"Exception 12: MACHINE CHECK\n\n" "Exception 12: MACHINE CHECK"
}; };
#define SCREEN_ATTR 0x1F // Bright white on blue background #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_ScreenPosX = 0;
static ULONG i386_ScreenPosY = 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 static void
i386PrintText(CHAR *pszText) i386PrintText(CHAR *pszText)
{ {
@ -96,18 +88,17 @@ PrintText(const CHAR *Format, ...)
static void static void
i386PrintFrames(PKTRAP_FRAME TrapFrame) i386PrintFrames(PKTRAP_FRAME TrapFrame)
{ {
FRAME *Frame; FRAME* Frame;
PrintText("Frames:\n"); PrintText("Frames:\n");
for (Frame =
#ifdef _M_IX86 #ifdef _M_IX86
for (Frame = (FRAME*)TrapFrame->Ebp; (FRAME*)TrapFrame->Ebp;
Frame != 0 && (ULONG_PTR)Frame < STACKADDR;
Frame = Frame->Next)
#else #else
for (Frame = (FRAME*)TrapFrame->TrapFrame; (FRAME*)TrapFrame->TrapFrame;
Frame != 0 && (ULONG_PTR)Frame < STACKADDR;
Frame = Frame->Next)
#endif #endif
Frame != NULL && (ULONG_PTR)Frame < STACKADDR;
Frame = Frame->Next)
{ {
PrintText("%p ", Frame->Address); PrintText("%p ", Frame->Address);
} }
@ -126,7 +117,8 @@ i386PrintExceptionText(ULONG TrapIndex, PKTRAP_FRAME TrapFrame, PKSPECIAL_REGIST
PrintText("An error occured in " VERSION "\n" PrintText("An error occured in " VERSION "\n"
"Report this error on the ReactOS Bug Tracker: https://jira.reactos.org\n\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 #ifdef _M_IX86
PrintText("EAX: %.8lx ESP: %.8lx CR0: %.8lx DR0: %.8lx\n", PrintText("EAX: %.8lx ESP: %.8lx CR0: %.8lx DR0: %.8lx\n",
TrapFrame->Eax, TrapFrame->HardwareEsp, Special->Cr0, TrapFrame->Dr0); 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); TrapFrame->Ecx, TrapFrame->Esi, Special->Cr2, TrapFrame->Dr2);
PrintText("EDX: %.8lx EDI: %.8lx CR3: %.8lx DR3: %.8lx\n", PrintText("EDX: %.8lx EDI: %.8lx CR3: %.8lx DR3: %.8lx\n",
TrapFrame->Edx, TrapFrame->Edi, Special->Cr3, TrapFrame->Dr3); TrapFrame->Edx, TrapFrame->Edi, Special->Cr3, TrapFrame->Dr3);
PrintText(" DR6: %.8lx\n", PrintText("%*s CR4: %.8lx DR6: %.8lx\n",
TrapFrame->Dr6); 41, "", Special->Cr4, TrapFrame->Dr6);
PrintText(" DR7: %.8lx\n\n", PrintText("%*s DR7: %.8lx\n",
TrapFrame->Dr7); 62, "", TrapFrame->Dr7);
/* NOTE: Segment registers are intrinsically 16 bits. Even if the x86 /* NOTE: Segment registers are intrinsically 16 bits. Even if the x86
* KTRAP_FRAME structure stores them as ULONG, only their lower 16 bits * KTRAP_FRAME structure stores them as ULONG, only their lower 16 bits
* are initialized. We thus cast them to USHORT before display. */ * 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); (USHORT)TrapFrame->SegCs, TrapFrame->Eip);
PrintText("DS: %.4lx ERROR CODE: %.8lx\n", PrintText(" DS: %.4lx ERROR CODE: %.8lx\n",
(USHORT)TrapFrame->SegDs, TrapFrame->ErrCode); (USHORT)TrapFrame->SegDs, TrapFrame->ErrCode);
PrintText("ES: %.4lx EFLAGS: %.8lx\n", PrintText(" ES: %.4lx EFLAGS: %.8lx\n",
(USHORT)TrapFrame->SegEs, TrapFrame->EFlags); (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); (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); (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); (USHORT)TrapFrame->HardwareSegSs, Special->Ldtr, Special->Tr);
i386PrintFrames(TrapFrame); // Display frames
InstructionPointer = (PUCHAR)TrapFrame->Eip;
#else #else
PrintText("RAX: %.8lx R8: %.8lx R12: %.8lx RSI: %.8lx\n", PrintText("RAX: %.8lx R8: %.8lx R12: %.8lx RSI: %.8lx\n",
TrapFrame->Rax, TrapFrame->R8, 0, TrapFrame->Rsi); 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", PrintText("RDX: %.8lx R11: %.8lx R15: %.8lx RSP: %.8lx\n",
TrapFrame->Rdx, TrapFrame->R11, 0, TrapFrame->Rsp); TrapFrame->Rdx, TrapFrame->R11, 0, TrapFrame->Rsp);
PrintText("CS: %.4lx RIP: %.8lx\n", PrintText(" CS: %.4lx RIP: %.8lx\n",
TrapFrame->SegCs, TrapFrame->Rip); TrapFrame->SegCs, TrapFrame->Rip);
PrintText("DS: %.4lx ERROR CODE: %.8lx\n", PrintText(" DS: %.4lx ERROR CODE: %.8lx\n",
TrapFrame->SegDs, TrapFrame->ErrorCode); TrapFrame->SegDs, TrapFrame->ErrorCode);
PrintText("ES: %.4lx EFLAGS: %.8lx\n", PrintText(" ES: %.4lx EFLAGS: %.8lx\n",
TrapFrame->SegEs, TrapFrame->EFlags); 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); 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); 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); 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; InstructionPointer = (PUCHAR)TrapFrame->Rip;
#endif #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[0], InstructionPointer[1],
InstructionPointer[2], InstructionPointer[3], InstructionPointer[2], InstructionPointer[3],
InstructionPointer[4], InstructionPointer[5], InstructionPointer[4], InstructionPointer[5],

View file

@ -82,7 +82,7 @@ MACRO(SAVE_CPU_REGS)
push eax push eax
ENDM 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: i386ExceptionIndex:
.long 0 .long 0