Thoughts from the EPS Windows Server Performance Team
Good morning AskPerf! 2009 is moving fast – it’s hard to believe we’re already into August! Today, we’re continuing on with our debugging focus. Over the next few posts, we’ll be looking at different command types within the debugger. Today’s post is brought to you by the letter … k. I know, I couldn’t resist the Sesame Street reference! Anyways …
The different k* commands in the debugger are used to display stack information of a thread. The k* commands work in both user-mode and kernel-mode debugging scenarios. Let’s take a look at the different flavors of the common k* commands and then some examples:
Now that we have an idea of what our options are, what does this look like in a debugger? I went ahead and created a manual dump of NOTEPAD.EXE via Task Manager on a 32-bit Windows Vista system and opened the dump file on a system with a debugger configured with the public symbols …
First of all, let’s list out the threads available in this dump file. To list out the threads, run the ~ command as shown below:
0:000> ~ . 0 Id: 3dc.61c Suspend: 0 Teb: 7ffde000 Unfrozen
Since there was only one thread running, there’s not too much I have to do in terms of looking at different threads. For the moment, let’s take a look at what each of our commands does, beginning with a simple k
0:000> k ChildEBP RetAddr 0019f7a0 7757f837 ntdll!KiFastSystemCallRet 0019f7a4 7757f86a user32!NtUserGetMessage+0xc 0019f7c0 00a71418 user32!GetMessageW+0x33 0019f800 00a7195d notepad!WinMain+0xec 0019f890 774c4911 notepad!_initterm_e+0x1a1 0019f89c 7763e4b6 kernel32!BaseThreadInitThunk+0xe 0019f8dc 7763e489 ntdll!__RtlUserThreadStart+0x23 0019f8f4 00000000 ntdll!_RtlUserThreadStart+0x1b
As we can see, from this stack we have some basic information concerning the modules and the functions. Now let’s add some of our other parameters, such as kb, kc, kp and kP:
0:000> kb ChildEBP RetAddr Args to Child 0019f7a0 7757f837 7757f86a 0019f7e4 00000000 ntdll!KiFastSystemCallRet 0019f7a4 7757f86a 0019f7e4 00000000 00000000 user32!NtUserGetMessage+0xc 0019f7c0 00a71418 0019f7e4 00000000 00000000 user32!GetMessageW+0x33 0019f800 00a7195d 00a70000 00000000 002d1e92 notepad!WinMain+0xec 0019f890 774c4911 7ffdf000 0019f8dc 7763e4b6 notepad!_initterm_e+0x1a1 0019f89c 7763e4b6 7ffdf000 77707155 00000000 kernel32!BaseThreadInitThunk+0xe 0019f8dc 7763e489 00a731ed 7ffdf000 00000000 ntdll!__RtlUserThreadStart+0x23 0019f8f4 00000000 00a731ed 7ffdf000 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> kc ntdll!KiFastSystemCallRet user32!NtUserGetMessage user32!GetMessageW notepad!WinMain notepad!_initterm_e kernel32!BaseThreadInitThunk ntdll!__RtlUserThreadStart ntdll!_RtlUserThreadStart
0:000> kp ChildEBP RetAddr 0019f7a0 7757f837 ntdll!KiFastSystemCallRet 0019f7a4 7757f86a user32!NtUserGetMessage+0xc 0019f7c0 00a71418 user32!GetMessageW+0x33 0019f800 00a7195d notepad!WinMain+0xec 0019f890 774c4911 notepad!_initterm_e+0x1a1 0019f89c 7763e4b6 kernel32!BaseThreadInitThunk+0xe 0019f8dc 7763e489 ntdll!__RtlUserThreadStart+0x23 0019f8f4 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> kP ChildEBP RetAddr 0019f7a0 7757f837 ntdll!KiFastSystemCallRet 0019f7a4 7757f86a user32!NtUserGetMessage+0xc 0019f7c0 00a71418 user32!GetMessageW+0x33 0019f800 00a7195d notepad!WinMain+0xec 0019f890 774c4911 notepad!_initterm_e+0x1a1 0019f89c 7763e4b6 kernel32!BaseThreadInitThunk+0xe 0019f8dc 7763e489 ntdll!__RtlUserThreadStart+0x23 0019f8f4 00000000 ntdll!_RtlUserThreadStart+0x1b
As we can see in the last two commands, since we only have the public symbols we cannot see all of the parameter information that we would if we had access to the private symbols. Let’s continue on with our examples – kv, kn, kf and some combinations of commands using the n parameter:
0:000> kv ChildEBP RetAddr Args to Child 0019f7a0 7757f837 7757f86a 0019f7e4 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0]) 0019f7a4 7757f86a 0019f7e4 00000000 00000000 user32!NtUserGetMessage+0xc (FPO: [4,0,0]) 0019f7c0 00a71418 0019f7e4 00000000 00000000 user32!GetMessageW+0x33 (FPO: [4,0,4]) 0019f800 00a7195d 00a70000 00000000 002d1e92 notepad!WinMain+0xec (FPO: [4,7,4]) 0019f890 774c4911 7ffdf000 0019f8dc 7763e4b6 notepad!_initterm_e+0x1a1 (FPO: [SEH]) 0019f89c 7763e4b6 7ffdf000 77707155 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [1,0,0]) 0019f8dc 7763e489 00a731ed 7ffdf000 00000000 ntdll!__RtlUserThreadStart+0x23 (FPO: [SEH]) 0019f8f4 00000000 00a731ed 7ffdf000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [2,2,0])
0:000> kn # ChildEBP RetAddr 00 0019f7a0 7757f837 ntdll!KiFastSystemCallRet 01 0019f7a4 7757f86a user32!NtUserGetMessage+0xc 02 0019f7c0 00a71418 user32!GetMessageW+0x33 03 0019f800 00a7195d notepad!WinMain+0xec 04 0019f890 774c4911 notepad!_initterm_e+0x1a1 05 0019f89c 7763e4b6 kernel32!BaseThreadInitThunk+0xe 06 0019f8dc 7763e489 ntdll!__RtlUserThreadStart+0x23 07 0019f8f4 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> kf Memory ChildEBP RetAddr 0019f7a0 7757f837 ntdll!KiFastSystemCallRet 4 0019f7a4 7757f86a user32!NtUserGetMessage+0xc 1c 0019f7c0 00a71418 user32!GetMessageW+0x33 40 0019f800 00a7195d notepad!WinMain+0xec 90 0019f890 774c4911 notepad!_initterm_e+0x1a1 c 0019f89c 7763e4b6 kernel32!BaseThreadInitThunk+0xe 40 0019f8dc 7763e489 ntdll!__RtlUserThreadStart+0x23 18 0019f8f4 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> kn 3 # ChildEBP RetAddr 00 0019f7a0 7757f837 ntdll!KiFastSystemCallRet 01 0019f7a4 7757f86a user32!NtUserGetMessage+0xc 02 0019f7c0 00a71418 user32!GetMessageW+0x33
0:000> kcn 3 # 00 ntdll!KiFastSystemCallRet 01 user32!NtUserGetMessage 02 user32!GetMessageW
0:000> kvn 3 # ChildEBP RetAddr Args to Child 00 0019f7a0 7757f837 7757f86a 0019f7e4 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0]) 01 0019f7a4 7757f86a 0019f7e4 00000000 00000000 user32!NtUserGetMessage+0xc (FPO: [4,0,0]) 02 0019f7c0 00a71418 0019f7e4 00000000 00000000 user32!GetMessageW+0x33 (FPO: [4,0,4])
As we can see in our last three examples, it is possible to combine parameters to get the top 3 frames on a stack trace (in this example) but we can always specify more. With that, we’ve come to the end of this post. We’ll be taking a look at some more commands in our next post. Until next time …
Additional Resources:
- CC Hameed