uint64_t TranslateLinearAddress(uint64_t directoryTableBase, uint64_t virtualAddress) { directoryTableBase &= ~0xf; uint64_t pageOffset = virtualAddress & ~(~0ul << PAGE_OFFSET_SIZE); uint64_t pte = ((virtualAddress >> 12) & (0x1ffll)); uint64_t pt = ((virtualAddress >> 21) & (0x1ffll)); uint64_t pd = ((virtualAddress >> 30) & (0x1ffll)); uint64_t pdp = ((virtualAddress >> 39) & (0x1ffll)); SIZE_T readsize = 0; uint64_t pdpe = 0; ReadPhysicalAddress((PVOID)(directoryTableBase + 8 * pdp), &pdpe, sizeof(pdpe), &readsize); if (~pdpe & 1) { DbgPrintEx(0, 0, "pdpe : %p", pdpe); return 0; } uint64_t pde = 0; ReadPhysicalAddress((PVOID)((pdpe & PMASK) + 8 * pd), &pde, sizeof(pde), &readsize); if (~pde & 1) { DbgPrintEx(0, 0, "pde : %p", pde); return 0; } /* 1GB large page, use pde's 12-34 bits */ if (pde & 0x80) return (pde & (~0ull << 42 >> 12)) + (virtualAddress & ~(~0ull << 30)); uint64_t pteAddr = 0; ReadPhysicalAddress((PVOID)((pde & PMASK) + 8 * pt), &pteAddr, sizeof(pteAddr), &readsize); if (~pteAddr & 1) { DbgPrintEx(0, 0, "pteAddr : %p", pteAddr); return 0; } /* 2MB large page */ if (pteAddr & 0x80) return (pteAddr & PMASK) + (virtualAddress & ~(~0ull << 21)); virtualAddress = 0; ReadPhysicalAddress((PVOID)((pteAddr & PMASK) + 8 * pte), &virtualAddress, sizeof(virtualAddress), &readsize); virtualAddress &= PMASK; if (!virtualAddress) { DbgPrintEx(0, 0, "virtualAddress : %p", virtualAddress); return 0; } return virtualAddress + pageOffset; }