在 WinDbg 中,你可以调用 !locks 来获取当前进程中所有临界区的列表。我想知道是否有办法调用调试引擎 API 来检索相同的列表。我想在 C++ 中构建的定制调试器中执行此操作,该调试器基于调试引擎 API 构建。有什么想法吗?
非常感谢。
在 WinDbg 中,你可以调用 !locks 来获取当前进程中所有临界区的列表。我想知道是否有办法调用调试引擎 API 来检索相同的列表。我想在 C++ 中构建的定制调试器中执行此操作,该调试器基于调试引擎 API 构建。有什么想法吗?
非常感谢。
这比较简单,你需要使用名为 RTL_CRITICAL_SECTION_DEBUG 的结构。我在打印输出中添加了注释:
0:011> dt ntdll!_RTL_CRITICAL_SECTION_DEBUG
+0x000 Type : Uint2B
+0x002 CreatorBackTraceIndex : Uint2B
+0x004 CriticalSection : Ptr32 _RTL_CRITICAL_SECTION // This is pointer to actual critical section
+0x008 ProcessLocksList : _LIST_ENTRY // All critical sections are chained in this doubly linked list
+0x010 EntryCount : Uint4B
+0x014 ContentionCount : Uint4B
+0x018 Flags : Uint4B
+0x01c CreatorBackTraceIndexHigh : Uint2B
+0x01e SpareUSHORT : Uint2B
如您所见,所有临界区都属于同一个全局列表,其中ProcessLocksList
一个临界区指向ProcessLocksList
下一个临界区(以及前一个临界区)。一旦知道所有ProcessLocksList
s 的地址,就可以通过从中减去 sizeof(void*) 来提取指向 RTL_CRITICAL_SECTION 结构的指针。
最后,第一个ProcessLocksList
条目的地址由 ntdll!RtlCriticalSectionList 给出。
以下命令是我上面所说的演示。它将打印出该过程中的所有关键部分:
!list "-t ntdll!_LIST_ENTRY.Flink -e -x \"ln poi(@$extret-0x4); dt ntdll!_RTL_CRITICAL_SECTION poi(@$extret-0x4)\" ntdll!RtlCriticalSectionList"
如果需要,请针对 x64 进行调整。
根据要求添加:这是 x64 的版本:
!list "-t ntdll!_LIST_ENTRY.Flink -e -x \"ln poi(@$extret-0x8); dt ntdll!_RTL_CRITICAL_SECTION poi(@$extret-0x8)\" ntdll!RtlCriticalSectionList"