enter image description here

Says the PDPT and PDs of the process are at the same physcial frames (pfns) in both processes.

The first process is winword.exe and the second process is calc.exe

The virtual address in the first case is the start of the virtual page containing the header of winword.exe, which VMMap shows to be in the shareable working set, but yet the output shows that the entry in the PDE hasn't ever even been touched.

I then try that virtual address in calc.exe, where VMMap shows no VAD allocation to that range, and it shows the same identical output.

This suggests to me that !pte is showing me the output of some other process, and I can't change it away from that and using .process alone and .process + .context with the correct dirbases (cr3/PML4 physical pages) doesnt work.

I'm using kd -kl, not livekd.

This also happens in windbg. Furthermore, I get the same pfns for both outputs, and those pfns change to a new set every time I reopen the debugger, which suggests that it is using the debuggers context. Is this a limitation with local debugging? I would have thought that a kernel driver would be able to do this correctly.

process /p does nothing, and !peb correctly shows the different PEBs of the 2 different processes, but !pte still appears to be using the context of kd

!vtop appears to be working correctly:

enter image description here

The problem is reproducible also on windbg (version 6.12) and also I tried version 10. This seems to be related. So does this (dreadful answer).

I translated the virtual address to the virtual address of its PTE using this technique (which is of course the same address that was attempted to be shown in the !pte output, and will be the same PTE address for that virtual address in the context of every process) and db shows nothing at that address either:

enter image description here

You still need to select the process context because the user side of the page tables as well as PML4 are mapped in differently for each process.

db lines up with new state of 0x13fe60000 according to !pte:

enter image description here

but !vtop works correctly:

enter image description here

I mean, the difference is that !vtop is accessing physical memory whereas !db and !pte access virtual memory. !peb works correctly and accesses virtual memory, but is user mode. It seems that it is struggling with reading kernel virtual addresses.

  • confirm observations with a real live kernel debugging sysinternals livekd and native local kernel debugging are kinda look alikes
    – blabb
    Mar 22, 2021 at 18:34
  • @blabb I mean it should be able to do this functionality in local debugging just fine, so it seems like a bug to me, unless I've misunderstood the usage. I will try to remote debug at some point -- perhaps a VM, never done it before though. Mar 22, 2021 at 18:41
  • @blabb If i can remember the equation for 4 level paging that allows you to translate a virtual address to the virtual address of the PTE that handles the virtual address, I will use dt as well Mar 22, 2021 at 19:04
  • @blabb Ok, I updated my question with that Mar 22, 2021 at 21:44

2 Answers 2



This person also noticed the issue and also came to the conclusion that it is showing the context of the debugger. He then said that it works on livekd ironically, which I can confirm.

enter image description here

enter image description here


Although, this doesn't explain why livekd works and why kd -kl doesn't, which is what I actually want to know

  • Livekd does not even need bcdedit /debug on to work while kd -kl needs /debug on they use different techniques and when you use livekd the cr3 register will be showing the eprocess->pcb.directorttablebase of livekd64.exe check with dx debugger.sessions[0].process.where( a=>a.kob.pcb.dbase==@cr3)
    – blabb
    Mar 23, 2021 at 4:07
  • 1
    and btw pavel lebedynskys answer might provide some clues toyou wrt lkd / live here
    – blabb
    Mar 23, 2021 at 5:25
  • @blabb yes I was right, only user addresses were being translated. Thanks for that link. .process /P solved the issue. On the documentation it said 'live debugging only' which I thought meant live and not local live, so I never tried it. I know that livekd uses some sort of crash dump made when it launches, but I'm not sure of the details – I'd like to know what specifically it does and what it consists of Mar 23, 2021 at 7:52
  • Ntsystemdebugcontrol sysdbg hacks prevista and official support with proper acls post vista sysinternal had an embedded resource driver and prevista windbg also had a helper [some utility and src code here ](crashdmp.wordpress.com/2014/08/04/livedump-1-0-is-available) alsi search my answers in so/windbg iirc i posted some code
    – blabb
    Mar 23, 2021 at 8:18
  • @blabb the point of this was to work out this question. It seems like mapped data files are all VAD prototype-pointer PTEs and the image files are all prototype-pointer PTEs, which doesn't make sense because multiple sources said all of the PPTEs in the view are deferred and created for data files when the VAD entry is created i.e. the view is mapped, but that implies that there are no PPTEs to point to, and why waste page table page allocation to do what a missing ... Mar 23, 2021 at 8:41

@blabb 's link is the correct answer for local debugging

Debugger cache is used only for live targets, local kd doesn't really need it. However, local kd still needs to decide how to translate virtual addresses to physical ones when you switch to a process. This is where the different .process options come into play:

.process: No translation is performed. All memory accesses are performed in the context of debugger's process. Kernel memory which is valid in any process context (pool, system PTE mappings etc.) will be displayed correctly, everything else (user memory, session space, page tables etc.) will not.

.process /p: User addresses are translated using the page directory of the specified process, so commands like !peb should work correctly. Kernel addresses are not translated, so things like session space and page tables may still be displayed incorrectly.

.process /P: All addresses, user and kernel, are translated. Use this option if you need to look at session space, page tables or other process-specific data in the kernel space.

I did not think it would be a bug -- the functionality to do it was clearly available. There has to be a specific usage to account for how local debugging works compared to livekd.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.