From 640f6a412aa6359f92c01dc6b01f7fa99eadf754 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 6 Feb 2023 19:33:48 +0200 Subject: [PATCH] Updated crash screen --- Core/Crash/CrashDetails.cpp | 39 +++++++++------ Core/Crash/CrashHandler.cpp | 80 ++++++++++++++++++++++++++++--- Core/Crash/Screens/Details.cpp | 10 ++-- Core/Crash/Screens/Main.cpp | 4 +- Core/Crash/Screens/StackFrame.cpp | 14 +++--- Core/Crash/UserHandler.cpp | 10 ++-- Core/crashhandler.hpp | 1 + 7 files changed, 115 insertions(+), 43 deletions(-) diff --git a/Core/Crash/CrashDetails.cpp b/Core/Crash/CrashDetails.cpp index e25b80e..5b3712e 100644 --- a/Core/Crash/CrashDetails.cpp +++ b/Core/Crash/CrashDetails.cpp @@ -30,68 +30,76 @@ SafeFunction void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame) fixme("Divide by zero exception\n"); UNUSED(Frame); } + SafeFunction void DebugExceptionHandler(CHArchTrapFrame *Frame) { - CrashHandler::EHPrint("\eDD2920System crashed!\n"); CrashHandler::EHPrint("Kernel triggered debug exception.\n"); UNUSED(Frame); } + SafeFunction void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame) { fixme("NMI exception"); UNUSED(Frame); } + SafeFunction void BreakpointExceptionHandler(CHArchTrapFrame *Frame) { fixme("Breakpoint exception"); UNUSED(Frame); } + SafeFunction void OverflowExceptionHandler(CHArchTrapFrame *Frame) { fixme("Overflow exception"); UNUSED(Frame); } + SafeFunction void BoundRangeExceptionHandler(CHArchTrapFrame *Frame) { fixme("Bound range exception"); UNUSED(Frame); } + SafeFunction void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame) { - CrashHandler::EHPrint("\eDD2920System crashed!\n"); CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n"); UNUSED(Frame); } + SafeFunction void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame) { fixme("Device not available exception"); UNUSED(Frame); } + SafeFunction void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame) { fixme("Double fault exception"); UNUSED(Frame); } + SafeFunction void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame) { fixme("Coprocessor segment overrun exception"); UNUSED(Frame); } + SafeFunction void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame) { fixme("Invalid TSS exception"); UNUSED(Frame); } + SafeFunction void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame) { fixme("Segment not present exception"); UNUSED(Frame); } + SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame) { CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; - CrashHandler::EHPrint("\eDD2920System crashed!\n"); - CrashHandler::EHPrint("More info about the exception:\n"); #if defined(__amd64__) CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip); #elif defined(__i386__) @@ -103,13 +111,9 @@ SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame) CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx); CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode); } + SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame) { - // staticbuffer(descbuf); - // staticbuffer(desc_ext); - // staticbuffer(desc_table); - // staticbuffer(desc_idx); - // staticbuffer(desc_tmp); CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; // switch (SelCode.Table) // { @@ -129,21 +133,19 @@ SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame) // memcpy(desc_tmp, "Unknown", 7); // break; // } - CrashHandler::EHPrint("\eDD2920System crashed!\n"); CrashHandler::EHPrint("Kernel performed an illegal operation.\n"); - CrashHandler::EHPrint("More info about the exception:\n"); CrashHandler::EHPrint("External: %d\n", SelCode.External); CrashHandler::EHPrint("Table: %d\n", SelCode.Table); CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx); } + SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame) { CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; - CrashHandler::EHPrint("\eDD2920System crashed!\n\eFFFFFF"); #if defined(__amd64__) - CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->rip); + CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->rip); #elif defined(__i386__) - CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->eip); + CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->eip); #elif defined(__aarch64__) #endif CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present"); @@ -161,7 +163,7 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame) #ifdef DEBUG uintptr_t CheckPageFaultAddress = 0; - CheckPageFaultAddress = CPU::x64::readcr2().PFLA; + CheckPageFaultAddress = CrashHandler::PageFaultAddress; if (CheckPageFaultAddress == 0) #ifdef __amd64__ CheckPageFaultAddress = Frame->rip; @@ -268,36 +270,43 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame) } #endif } + SafeFunction void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("x87 floating point exception"); UNUSED(Frame); } + SafeFunction void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Alignment check exception"); UNUSED(Frame); } + SafeFunction void MachineCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Machine check exception"); UNUSED(Frame); } + SafeFunction void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("SIMD floating point exception"); UNUSED(Frame); } + SafeFunction void VirtualizationExceptionHandler(CHArchTrapFrame *Frame) { fixme("Virtualization exception"); UNUSED(Frame); } + SafeFunction void SecurityExceptionHandler(CHArchTrapFrame *Frame) { fixme("Security exception"); UNUSED(Frame); } + SafeFunction void UnknownExceptionHandler(CHArchTrapFrame *Frame) { fixme("Unknown exception"); diff --git a/Core/Crash/CrashHandler.cpp b/Core/Crash/CrashHandler.cpp index e3662f0..744b8dd 100644 --- a/Core/Crash/CrashHandler.cpp +++ b/Core/Crash/CrashHandler.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -25,9 +26,11 @@ NewLock(UserInputLock); namespace CrashHandler { + uintptr_t PageFaultAddress = 0; void *EHIntFrames[INT_FRAMES_MAX]; static bool ExceptionOccurred = false; int SBIdx = 255; + SafeFunction void printfWrapper(char c, void *unused) { Display->Print(c, SBIdx, true); @@ -146,6 +149,70 @@ namespace CrashHandler EHPrint(" \eAAF00F%s", CPU::Vendor()); EHPrint(" \eAA00FF%s", CPU::Name()); Display->SetBufferCursor(SBIdx, 0, fi.Height + 10); + + /* https://imgflip.com/i/77slbl */ + if ((Random::rand32() % 100) >= 98) + { + debug("Easter egg activated!"); + int BaseXOffset = sb->Width - 14; + int BaseYOffset = 8; + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 0, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 0, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 0, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 0, 0x21852E, SBIdx); + + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 8, BaseYOffset + 1, 0x21852E, SBIdx); + + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 2, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 2, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 2, 0xFFFFFF, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 2, 0x000000, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 2, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 2, 0xFFFFFF, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 2, 0x000000, SBIdx); + Display->SetPixel(BaseXOffset + 8, BaseYOffset + 2, 0x21852E, SBIdx); + + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 3, 0x21852E, SBIdx); + + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 4, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 4, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 4, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 4, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 4, 0xA84832, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 4, 0xA84832, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 4, 0xA84832, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 4, 0xA84832, SBIdx); + + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 5, 0x21852E, SBIdx); + + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 6, 0x1216FF, SBIdx); + + Display->SetBuffer(SBIdx); + } } SafeFunction void DisplayBottomOverlay() @@ -246,7 +313,7 @@ namespace CrashHandler EHPrint("exit - Shutdown the OS.\n"); EHPrint("reboot - Reboot the OS.\n"); EHPrint("help - Display this help message.\n"); - EHPrint("showbuf - Display the contents of a screen buffer.\n"); + EHPrint("showbuf,sb - Display the contents of a screen buffer.\n"); EHPrint(" - A sleep timer will be enabled. This will cause the OS to sleep for an unknown amount of time.\n"); EHPrint(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n"); EHPrint("ifr - Show interrupt frames.\n"); @@ -281,7 +348,7 @@ namespace CrashHandler Display->SetBuffer(SBIdx); CPU::Stop(); } - else if (strncmp(Input, "showbuf", 7) == 0) + else if (strncmp(Input, "showbuf", 7) == 0 || strncmp(Input, "sb", 2) == 0) { char *arg = TrimWhiteSpace(Input + 7); int tmpidx = SBIdx; @@ -475,7 +542,7 @@ namespace CrashHandler EHPrint("\e44AA000: %#lx\n", CPU::x64::readcr0()); break; case '2': - EHPrint("\e44AA002: %#lx\n", CPU::x64::readcr2()); + EHPrint("\e44AA002: %#lx\n", PageFaultAddress); break; case '3': EHPrint("\e44AA003: %#lx\n", CPU::x64::readcr3()); @@ -592,6 +659,7 @@ namespace CrashHandler CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data; #if defined(__amd64__) error("Exception: %#llx", Frame->InterruptNumber); + PageFaultAddress = CPU::x64::readcr2().PFLA; if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA) { @@ -616,7 +684,7 @@ namespace CrashHandler debug("CPU %ld data is valid", data->ID); if (data->CurrentThread->Security.IsCritical) { - debug("Critical thread died"); + debug("Critical thread \"%s\"(%d) died", data->CurrentThread->Name, data->CurrentThread->ID); if (TaskManager) TaskManager->Panic(); Display->CreateBuffer(0, 0, SBIdx); @@ -637,7 +705,7 @@ namespace CrashHandler Display->SetBufferCursor(SBIdx, 0, 0); CPU::x64::CR0 cr0 = CPU::x64::readcr0(); - CPU::x64::CR2 cr2 = CPU::x64::readcr2(); + CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; CPU::x64::CR3 cr3 = CPU::x64::readcr3(); CPU::x64::CR4 cr4 = CPU::x64::readcr4(); CPU::x64::CR8 cr8 = CPU::x64::readcr8(); @@ -699,7 +767,7 @@ namespace CrashHandler debug("Reading control registers..."); crashdata.Frame = Frame; crashdata.cr0 = CPU::x64::readcr0(); - crashdata.cr2 = CPU::x64::readcr2(); + crashdata.cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; crashdata.cr3 = CPU::x64::readcr3(); crashdata.cr4 = CPU::x64::readcr4(); crashdata.cr8 = CPU::x64::readcr8(); diff --git a/Core/Crash/Screens/Details.cpp b/Core/Crash/Screens/Details.cpp index 277207e..7c3eb47 100644 --- a/Core/Crash/Screens/Details.cpp +++ b/Core/Crash/Screens/Details.cpp @@ -35,14 +35,10 @@ namespace CrashHandler if (cpu) { EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu); - EHPrint("Syscalls Stack: %#lx\n", cpu->SystemCallStack); - EHPrint("TempStack: %#lx\n", cpu->TempStack); - EHPrint("Core Stack: %#lx\n", cpu->Stack); - EHPrint("Core ID: %ld\n", cpu->ID); - EHPrint("Error Code: %ld\n", cpu->ErrorCode); + EHPrint("Syscalls Stack: %#lx, TempStack: %#lx\n", cpu->SystemCallStack, cpu->TempStack); + EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode); EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false"); - EHPrint("Current Process: %#lx\n", cpu->CurrentProcess); - EHPrint("Current Thread: %#lx\n", cpu->CurrentThread); + EHPrint("Current Process: %#lx, Current Thread: %#lx\n", cpu->CurrentProcess, cpu->CurrentThread); EHPrint("Arch Specific Data: %#lx\n", cpu->Data); EHPrint("Checksum: 0x%X\n", cpu->Checksum); } diff --git a/Core/Crash/Screens/Main.cpp b/Core/Crash/Screens/Main.cpp index be3f643..645d8f8 100644 --- a/Core/Crash/Screens/Main.cpp +++ b/Core/Crash/Screens/Main.cpp @@ -270,9 +270,9 @@ namespace CrashHandler CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; #if defined(__amd64__) - EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->rip); + EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->rip); #elif defined(__i386__) - EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->eip); + EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->eip); #elif defined(__aarch64__) #endif EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present"); diff --git a/Core/Crash/Screens/StackFrame.cpp b/Core/Crash/Screens/StackFrame.cpp index 8a85e9c..9ecc6a2 100644 --- a/Core/Crash/Screens/StackFrame.cpp +++ b/Core/Crash/Screens/StackFrame.cpp @@ -53,31 +53,29 @@ namespace CrashHandler } if (data.Process && data.Thread) { - EHPrint("\n\n\eFAFAFATracing thread RIP history..."); + EHPrint("\n\n\eFAFAFATracing thread instruction pointer history..."); SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable; if (!sh) EHPrint("\n\eFFA500Warning: No symbol table available."); int SameItr = 0; uintptr_t LastRIP = 0; - for (int i = 0; i < 128; i++) + for (size_t i = 0; i < sizeof(data.Thread->IPHistory) / sizeof(data.Thread->IPHistory[0]); i++) { - if (data.Thread->IPHistory[i] == 0) - break; if (data.Thread->IPHistory[i] == LastRIP) { SameItr++; - if (SameItr > 3) + if (SameItr > 2) continue; } else SameItr = 0; LastRIP = data.Thread->IPHistory[i]; if (!sh) - EHPrint("\n\e2565CC%p", data.Thread->IPHistory[i]); + EHPrint("\n\eCCCCCC%d: \e2565CC%p", i, data.Thread->IPHistory[i]); else - EHPrint("\n\e2565CC%p\e7925CC-\e25CCC9%s", data.Thread->IPHistory[i], sh->GetSymbolFromAddress(data.Thread->IPHistory[i])); + EHPrint("\n\eCCCCCC%d: \e2565CC%p\e7925CC-\e25CCC9%s", i, data.Thread->IPHistory[i], sh->GetSymbolFromAddress(data.Thread->IPHistory[i])); } - EHPrint("\n\e7925CCNote: \e2565CCSame RIPs are not shown more than 3 times.\n"); + EHPrint("\n\e7925CCNote: \e2565CCSame instruction pointers are not shown more than 3 times.\n"); } } } diff --git a/Core/Crash/UserHandler.cpp b/Core/Crash/UserHandler.cpp index e1e21b2..dedce6f 100644 --- a/Core/Crash/UserHandler.cpp +++ b/Core/Crash/UserHandler.cpp @@ -35,7 +35,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) { CPU::x64::CR0 cr0 = CPU::x64::readcr0(); - CPU::x64::CR2 cr2 = CPU::x64::readcr2(); + CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = CrashHandler::PageFaultAddress}; CPU::x64::CR3 cr3 = CPU::x64::readcr3(); CPU::x64::CR4 cr4 = CPU::x64::readcr4(); CPU::x64::CR8 cr8 = CPU::x64::readcr8(); @@ -179,13 +179,13 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) uintptr_t CheckPageFaultAddress = 0; CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; #if defined(__amd64__) - CheckPageFaultAddress = CPU::x64::readcr2().PFLA; + CheckPageFaultAddress = CrashHandler::PageFaultAddress; if (CheckPageFaultAddress == 0) CheckPageFaultAddress = Frame->rip; - error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->rip); + error("An exception occurred at %#lx by %#lx", CrashHandler::PageFaultAddress, Frame->rip); #elif defined(__i386__) - error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->eip); + error("An exception occurred at %#lx by %#lx", CrashHandler::PageFaultAddress, Frame->eip); #elif defined(__aarch64__) #endif error("Page: %s", params.P ? "Present" : "Not Present"); @@ -303,7 +303,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) #endif if (CurCPU) - if (CurCPU->CurrentThread->Stack->Expand(CPU::x64::readcr2().raw)) + if (CurCPU->CurrentThread->Stack->Expand(CrashHandler::PageFaultAddress)) { debug("Stack expanded"); TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready; diff --git a/Core/crashhandler.hpp b/Core/crashhandler.hpp index 6742c4d..4073633 100644 --- a/Core/crashhandler.hpp +++ b/Core/crashhandler.hpp @@ -8,6 +8,7 @@ namespace CrashHandler { + extern uintptr_t PageFaultAddress; extern void *EHIntFrames[INT_FRAMES_MAX]; void EHPrint(const char *Format, ...);