Search This Blog

Saturday 30 August 2014

WinDbg : the !thread and the .thread Commands

WinDbg : !thread

The !thread extension command lists down some very useful information related to threads. depending on what switches are used, it can display information about one or all threads. Below are some examples.

kd> !thread
THREAD 851d8d48  Cid 08b4.08b8  Teb: 7ffdf000 Win32Thread: fe9fddd8 RUNNING on processor 0
IRP List:
    849bc610: (0006,0094) Flags: 00060000  Mdl: 00000000
Not impersonating
DeviceMap                 90cda830
Owning Process            851d1348       Image:         NotMyfault.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      3020           Ticks: 1 (0:00:00:00.015)
Context Switch Count      180            IdealProcessor: 0             
UserTime                  00:00:00.000
KernelTime                00:00:00.031
Win32 Start Address 0x00402627
Stack Init 91387fd0 Current 91387af8 Base 91388000 Limit 91385000 Call 0
Priority 12 BasePriority 8 UnusualBoost 0 ForegroundBoost 2 IoPriority 2 PagePriority 5
ChildEBP RetAddr  Args to Child              
91387b3c 92deb579 badb0d00 839a9240 940b3800 nt!KiTrap0E+0x2cf (FPO: [0,0] TrapFrame @ 91387b3c)
WARNING: Stack unwind information not available. Following frames may be wrong.
91387bb8 92deb849 849bc610 91387bfc 92deb8ac myfault+0x579
91387bc4 92deb8ac 852540f0 00000001 00000000 myfault+0x849
91387bfc 8263f593 850bff08 849bc610 849bc610 myfault+0x8ac
91387c14 8283399f 852540f0 849bc610 849bc680 nt!IofCallDriver+0x63
91387c34 82836b71 850bff08 852540f0 00000000 nt!IopSynchronousServiceTail+0x1f8
91387cd0 8287d3f4 850bff08 849bc610 00000000 nt!IopXxxControlFile+0x6aa
91387d04 826461ea 000000bc 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
91387d04 77be70b4 000000bc 00000000 00000000 nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 91387d34)

0012f994 00000000 00000000 00000000 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])

WinDbg : .thread


The .thread (dot thread) command is used to switch the debugger into the context of the thread. When in user mode, we usually attach to a particular process or the dump generated in user mode is of one process. However, in kernel mode, the dump or debugger attachment will be generic and to switch the context into that of the current process we would need the .process command. Examples below.

A total list of running threads in the system can be found with the !stacks command as explained here. Once we find the thread we are interested in we can switch context to it.

Here is a snipped output from the !stacks command for the process lsass.exe.


                            [84cdc860 lsass.exe]

 208.00021c  84ce1688 0000947 Blocked    Stack paged out
 208.000220  848f7b20 00008b5 Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeWaitForSingleObject+0x393
                                        nt!NtWaitForSingleObject+0xc6
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet
 208.000224  84d047a8 00001ac Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeWaitForMultipleObjects+0x535
                                        nt!ObpWaitForMultipleObjects+0x262
                                        nt!NtWaitForMultipleObjects+0xcd
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet
 208.000228  84d044c0 00008e4 Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeRemoveQueueEx+0x4f8
                                        nt!IoRemoveIoCompletion+0x23
                                        nt!NtWaitForWorkViaWorkerFactory+0x1a1
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet
 208.00022c  84cfb030 0000901 Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeRemoveQueueEx+0x4f8
                                        nt!IoRemoveIoCompletion+0x23
                                        nt!NtWaitForWorkViaWorkerFactory+0x1a1
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet
 208.000234  84d103a0 0000294 Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeRemoveQueueEx+0x4f8
                                        nt!IoRemoveIoCompletion+0x23
                                        nt!NtWaitForWorkViaWorkerFactory+0x1a1
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet
 208.000270  84d23378 00006a8 Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeRemoveQueueEx+0x4f8
                                        nt!IoRemoveIoCompletion+0x23
                                        nt!NtWaitForWorkViaWorkerFactory+0x1a1
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet
 208.00033c  84d72a60 00000aa Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeRemoveQueueEx+0x4f8
                                        nt!IoRemoveIoCompletion+0x23
                                        nt!NtWaitForWorkViaWorkerFactory+0x1a1
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet
 208.000394  84eed338 00008c2 Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeWaitForSingleObject+0x393
                                        nt!EtwpReceiveNotification+0xf4
                                        nt!NtTraceControl+0x281
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet
 208.000774  850cad48 00006b1 Blocked    nt!KiSwapContext+0x26
                                        nt!KiSwapThread+0x266
                                        nt!KiCommitThreadWait+0x1df
                                        nt!KeDelayExecutionThread+0x2aa
                                        nt!NtDelayExecution+0x8d
                                        nt!KiFastCallEntry+0x12a
                                        ntdll!KiFastSystemCallRet

then we change to the context of the thread we are interested in using teh .thread command.

kd> .thread /p /r 84eed338
Implicit thread is now 84eed338
Implicit process is now 84cdc860
Loading User Symbols
............................................................

************* Symbol Loading Error Summary **************
Module name            Error
myfault                The system cannot find the file specified

You can troubleshoot most symbol related issues by turning on symbol loading diagnostics (!sym noisy) and repeating the command that caused symbols to be loaded.
You should also verify that your symbol search path (.sympath) is correct.
kd> kn
  *** Stack trace for last set context - .thread/.cxr resets it
 # ChildEBP RetAddr  
00 8a2d3b88 8268669d nt!KiSwapContext+0x26
01 8a2d3bc0 826854f7 nt!KiSwapThread+0x266
02 8a2d3be8 8267f0cf nt!KiCommitThreadWait+0x1df
03 8a2d3c60 827f14a4 nt!KeWaitForSingleObject+0x393
04 8a2d3cb8 82859c3c nt!EtwpReceiveNotification+0xf4
05 8a2d3d14 826461ea nt!NtTraceControl+0x281
06 8a2d3d14 77be70b4 nt!KiFastCallEntry+0x12a
07 0071fb44 77be6924 ntdll!KiFastSystemCallRet
08 0071fb48 77bbf505 ntdll!ZwTraceControl+0xc
09 0071fb78 76753c45 ntdll!EtwpNotificationThread+0x3d
0a 0071fb84 77c037f5 kernel32!BaseThreadInitThunk+0xe
0b 0071fbc4 77c037c8 ntdll!__RtlUserThreadStart+0x70
0c 0071fbdc 00000000 ntdll!_RtlUserThreadStart+0x1b

Comparing he stack trace from the !stacks and the current stack we know that we are in the right context.

We will see seeing practical uses of these commands in later posts.


No comments:

Post a Comment