diff --git a/Core/Crash/UserHandler.cpp b/Core/Crash/UserHandler.cpp index 0160f12..6054cb9 100644 --- a/Core/Crash/UserHandler.cpp +++ b/Core/Crash/UserHandler.cpp @@ -177,8 +177,13 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) } case CPU::x64::PageFault: { + uint64_t CheckPageFaultAddress = 0; CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; #if defined(__amd64__) + CheckPageFaultAddress = CPU::x64::readcr2().PFLA; + if (CheckPageFaultAddress == 0) + CheckPageFaultAddress = Frame->rip; + error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->rip); #elif defined(__i386__) error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->eip); @@ -201,21 +206,21 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) if (CurCPU) { Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable); - bool PageAvailable = vma.Check((void *)CPU::x64::readcr2().PFLA); + bool PageAvailable = vma.Check((void *)CheckPageFaultAddress); debug("Page available (Check(...)): %s. %s", PageAvailable ? "Yes" : "No", (params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result."); if (PageAvailable) { - bool Present = vma.Check((void *)CPU::x64::readcr2().PFLA); - bool ReadWrite = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::RW); - bool User = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::US); - bool WriteThrough = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PWT); - bool CacheDisabled = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PCD); - bool Accessed = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::A); - bool Dirty = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::D); - bool Global = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::G); + bool Present = vma.Check((void *)CheckPageFaultAddress); + bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW); + bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US); + bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT); + bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD); + bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A); + bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D); + bool Global = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G); /* ... */ debug("Page available: %s", Present ? "Yes" : "No"); @@ -226,6 +231,74 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) debug("Page accessed: %s", Accessed ? "Yes" : "No"); debug("Page dirty: %s", Dirty ? "Yes" : "No"); debug("Page global: %s", Global ? "Yes" : "No"); + + if (Present) + { + uint64_t CheckPageFaultLinearAddress = (uint64_t)CheckPageFaultAddress; + CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000; + debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress); + + Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uint64_t)CheckPageFaultLinearAddress); + debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d", + CheckPageFaultLinearAddress, + Index.PMLIndex, + Index.PDPTEIndex, + Index.PDEIndex, + Index.PTEIndex); + Memory::PageMapLevel4 PML4 = CurCPU->CurrentProcess->PageTable->Entries[Index.PMLIndex]; + + Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uint64_t)PML4.GetAddress() << 12); + Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uint64_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); + Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uint64_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); + + debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx", + Index.PMLIndex, 0, 0, 0, + PML4.Present ? "1" : "0", + PML4.ReadWrite ? "1" : "0", + PML4.UserSupervisor ? "1" : "0", + PML4.WriteThrough ? "1" : "0", + PML4.CacheDisable ? "1" : "0", + PML4.Accessed ? "1" : "0", + PML4.ExecuteDisable ? "1" : "0", + PML4.GetAddress() << 12); + + debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx", + Index.PMLIndex, Index.PDPTEIndex, 0, 0, + PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0", + PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0", + PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0", + PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0", + PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0", + PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0", + PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0", + PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); + + debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx", + Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0, + PDE->Entries[Index.PDEIndex].Present ? "1" : "0", + PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0", + PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0", + PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0", + PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0", + PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0", + PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0", + PDE->Entries[Index.PDEIndex].GetAddress() << 12); + + debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx", + Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex, + PTE->Entries[Index.PTEIndex].Present ? "1" : "0", + PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0", + PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0", + PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0", + PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0", + PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0", + PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0", + PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0", + PTE->Entries[Index.PTEIndex].Global ? "1" : "0", + PTE->Entries[Index.PTEIndex].ProtectionKey, + PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0", + PTE->Entries[Index.PTEIndex].GetAddress() << 12); + } } } #endif