The WinDBG command !ntsdexts.locks makes traversing a process's critical sections painless. However, knowing how to manually enumerate a process's critical sections would be useful to solve the issue in some occasion. Critical Section Corruption in Memory Dump Analysis Vol 2 by Dmitry Vostokov provides such an example. Thanks to the article by Matt Pietrek and Russ Osterlund -- Break Free of Code Deadlocks in Critical Sections Under Windows, it sheds light on how to do it.
A critical section is defined as following. Extra plus signs are used to indicate extra indentation.
0:041> dt -r1 _RTL_CRITICAL_SECTION
ntdll!_RTL_CRITICAL_SECTION
+0x000 DebugInfo : Ptr32 _RTL_CRITICAL_SECTION_DEBUG
+++0x000 Type : Uint2B
+++0x002 CreatorBackTraceIndex : Uint2B
+++0x004 CriticalSection : Ptr32 _RTL_CRITICAL_SECTION
+++0x008 ProcessLocksList : _LIST_ENTRY
+++0x010 EntryCount : Uint4B
+++0x014 ContentionCount : Uint4B
+++0x018 Flags : Uint4B
+++0x01c CreatorBackTraceIndexHigh : Uint2B
+++0x01e SpareUSHORT : Uint2B
+0x004 LockCount : Int4B+++0x002 CreatorBackTraceIndex : Uint2B
+++0x004 CriticalSection : Ptr32 _RTL_CRITICAL_SECTION
+++0x008 ProcessLocksList : _LIST_ENTRY
+++0x010 EntryCount : Uint4B
+++0x014 ContentionCount : Uint4B
+++0x018 Flags : Uint4B
+++0x01c CreatorBackTraceIndexHigh : Uint2B
+++0x01e SpareUSHORT : Uint2B
+0x008 RecursionCount : Int4B
+0x00c OwningThread : Ptr32 Void
+0x010 LockSemaphore : Ptr32 Void
+0x014 SpinCount : Uint4B
ProcessLocksList is a doubly linked list. It links to ProcessLocksList's in other critical sections.
0:041> !locks -v
CritSec ntdll!RtlCriticalSectionLock+0 at 77de4190
LockCount NOT LOCKED
RecursionCount 0
OwningThread 0
EntryCount 0
ContentionCount 3
......
CritSec +45bc3f4 at 045bc3f4
LockCount NOT LOCKED
RecursionCount 0
OwningThread 0
EntryCount 0
ContentionCount 0
CritSec +722dee0 at 0722dee0
LockCount NOT LOCKED
RecursionCount 0
OwningThread 0
EntryCount 0
ContentionCount 0
CritSec +722e128 at 0722e128
WaiterWoken No
LockCount 0
RecursionCount 1
OwningThread a0c
EntryCount 0
ContentionCount 0
*** Locked
Let us start with the last third critical section.
0:041> dt -r1 _RTL_CRITICAL_SECTION 045bc3f4
ntdll!_RTL_CRITICAL_SECTION
+0x000 DebugInfo : 0x07594d58 _RTL_CRITICAL_SECTION_DEBUG
+++0x000 Type : 0
+++0x002 CreatorBackTraceIndex : 0
+++0x004 CriticalSection : 0x045bc3f4 _RTL_CRITICAL_SECTION
+++0x008 ProcessLocksList : _LIST_ENTRY [ 0x7595788 - 0x75946a8 ]
+++0x010 EntryCount : 0
+++0x014 ContentionCount : 0
+++0x018 Flags : 0
+++0x01c CreatorBackTraceIndexHigh : 0
+++0x01e SpareUSHORT : 0
+0x004 LockCount : -1
+0x008 RecursionCount : 0
+0x00c OwningThread : (null)
+0x010 LockSemaphore : (null)
+0x014 SpinCount : 0
The offset of ProcessLocksList in _RTL_CRITICAL_SECTION_DEBUG is 8.
0:041> dt -r1 _RTL_CRITICAL_SECTION_DEBUG 0x7595788-0x8
ntdll!_RTL_CRITICAL_SECTION_DEBUG
+0x000 Type : 0
+0x002 CreatorBackTraceIndex : 0
+0x004 CriticalSection : 0x0722dee0 _RTL_CRITICAL_SECTION ; last second critical section
+++0x000 DebugInfo : 0x07595780 _RTL_CRITICAL_SECTION_DEBUG
+++0x004 LockCount : -1
+++0x008 RecursionCount : 0
+++0x00c OwningThread : (null)
+++0x010 LockSemaphore : (null)
+++0x014 SpinCount : 0
+0x008 ProcessLocksList : _LIST_ENTRY [ 0x7594270 - 0x7594d60 ]
+++0x000 Flink : 0x07594270 _LIST_ENTRY [ 0x77de4780 - 0x7595788 ]
+++0x004 Blink : 0x07594d60 _LIST_ENTRY [ 0x7595788 - 0x75946a8 ]
+0x010 EntryCount : 0
+0x014 ContentionCount : 0
+0x018 Flags : 0
+0x01c CreatorBackTraceIndexHigh : 0
+0x01e SpareUSHORT : 0
0:041> dt -r1 _RTL_CRITICAL_SECTION_DEBUG 0x7594270-0x8
ntdll!_RTL_CRITICAL_SECTION_DEBUG
+0x000 Type : 0
+0x002 CreatorBackTraceIndex : 0
+0x004 CriticalSection : 0x0722e128 _RTL_CRITICAL_SECTION ; last critical section
+++0x000 DebugInfo : 0x07594268 _RTL_CRITICAL_SECTION_DEBUG
+++0x004 LockCount : -2
+++0x008 RecursionCount : 1
+++0x00c OwningThread : 0x00000a0c
+++0x010 LockSemaphore : (null)
+++0x014 SpinCount : 0
+0x008 ProcessLocksList : _LIST_ENTRY [ 0x77de4780 - 0x7595788 ]
+++0x000 Flink : 0x77de4780 _LIST_ENTRY [ 0x77de42d8 - 0x7594270 ]
+++0x004 Blink : 0x07595788 _LIST_ENTRY [ 0x7594270 - 0x7594d60 ]
+0x010 EntryCount : 0
+0x014 ContentionCount : 0
+0x018 Flags : 0
+0x01c CreatorBackTraceIndexHigh : 0
+0x01e SpareUSHORT : 0
0:041> dt -r1 _RTL_CRITICAL_SECTION_DEBUG 0x77de4780-0x8
ntdll!_RTL_CRITICAL_SECTION_DEBUG
+0x000 Type : 0
+0x002 CreatorBackTraceIndex : 0
+0x004 CriticalSection : (null) ; tail
+0x008 ProcessLocksList : _LIST_ENTRY [ 0x77de42d8 - 0x7594270 ]
+++0x000 Flink : 0x77de42d8 _LIST_ENTRY [ 0x77de4768 - 0x77de4780 ]
+++0x004 Blink : 0x07594270 _LIST_ENTRY [ 0x77de4780 - 0x7595788 ]
+0x010 EntryCount : 0x3774
+0x014 ContentionCount : 0
+0x018 Flags : 0
+0x01c CreatorBackTraceIndexHigh : 0
+0x01e SpareUSHORT : 0
0:041> dt -r1 _RTL_CRITICAL_SECTION_DEBUG 0x77de42d8-0x8
ntdll!_RTL_CRITICAL_SECTION_DEBUG
+0x000 Type : 0
+0x002 CreatorBackTraceIndex : 0
+0x004 CriticalSection : 0x77de4190 _RTL_CRITICAL_SECTION ; first critical section
+++0x000 DebugInfo : 0x77de42d0 _RTL_CRITICAL_SECTION_DEBUG
+++0x004 LockCount : -1
+++0x008 RecursionCount : 0
+++0x00c OwningThread : (null)
+++0x010 LockSemaphore : 0x0000080c
+++0x014 SpinCount : 0x2000003
+0x008 ProcessLocksList : _LIST_ENTRY [ 0x77de4768 - 0x77de4780 ]
+++0x000 Flink : 0x77de4768 _LIST_ENTRY [ 0x77de6208 - 0x77de42d8 ]
+++0x004 Blink : 0x77de4780 _LIST_ENTRY [ 0x77de42d8 - 0x7594270 ]
+0x010 EntryCount : 0
+0x014 ContentionCount : 3
+0x018 Flags : 0
+0x01c CreatorBackTraceIndexHigh : 0
+0x01e SpareUSHORT : 0
The same approach could be used to traverse critical sections backward.
0 comments:
Post a Comment