控制线程和进程

有关调试器引擎中的线程和进程的概述,请参阅 线程和进程

发生事件时,事件线程和事件进程将设置为发生事件的 (操作系统或虚拟) 的线程和进程。 可以分别使用 GetEventThreadGetEventProcess 找到它们。

隐式线程和进程

在内核模式调试中,调试器引擎将使用 隐式进程 来确定在执行虚拟到物理地址转换时要使用的虚拟地址空间,例如,在 VirtualToPhysicalReadVirtual 方法中。 发生事件时,隐式进程设置为当前进程。

可以使用 SetImplicitProcessDataOffset 更改隐式进程。 若要确定隐式进程,请使用 GetImplicitProcessDataOffset

注意 在实时内核调试会话期间设置 断点 时,调试器引擎会将断点的虚拟地址传递给目标,目标将设置断点。 在这种情况下,处理断点时仅使用目标的进程上下文;隐式进程的 值无关紧要。

在内核模式调试中,调试器引擎将使用 隐式线程 来确定一些目标 寄存器。 这包括处理器堆栈 (请参阅 GetStackOffset) ,帧偏移量 (请参阅 GetFrameOffset) ,指令偏移量 (请参阅 GetInstructionOffset) 。 发生事件时,隐式线程设置为当前线程。

可以使用 SetImplicitThreadDataOffset 更改隐式线程。 若要确定隐式线程,请使用 GetImplicitThreadDataOffset

并非所有寄存器都由隐式线程确定。 更改隐式线程时,某些寄存器将保持不变。

警告 隐式进程和隐式线程是独立的。 如果隐式线程不属于隐式进程,则隐式线程的用户和会话状态将位于错误的虚拟地址空间中,并且尝试访问此信息将导致错误或提供不正确的结果。 访问内核内存时不会出现此问题,因为内核内存地址在所有虚拟地址空间中都是恒定的。 因此,可以独立于隐式进程访问位于内核内存中的隐式线程的信息。

线程

调试器 引擎使用引擎线程 ID 来标识目标的每个操作系统线程和每个虚拟线程。

停止目标时,每个线程还具有相对于其所属进程的索引。 对于任何进程,进程中第一个线程的索引为零,最后一个线程的索引是进程中的线程数减 1。 可以使用 GetNumberThreads 找到当前进程中的线程数。 可以使用 GetTotalNumberThreads 找到当前目标中所有进程中的线程总数。

可以使用 GetThreadIdsByIndex 从当前进程中一个或多个线程的索引中找到引擎线程 ID 和系统线程 ID。

引擎维护有关每个线程的几条信息。 此信息可以查询当前线程,并可用于查找线程的引擎线程 ID。

仅) (用户模式调试的系统线程 ID
可以使用 GetCurrentThreadSystemId 找到当前线程的系统线程 ID。 对于给定的系统线程 ID,可以使用 GetThreadIdBySystemId 找到相应的引擎线程 ID。

线程环境块 (TEB)
可以使用 GetCurrentThreadTeb 找到当前线程的 TEB 地址。 对于给定的 TEB 地址,可以使用 GetThreadIdByTeb 找到相应的引擎线程 ID。 在内核模式调试中, (虚拟) 线程的 TEB 是发生最后一个事件时在相应处理器上运行的系统线程的 TEB。

数据偏移量
在用户模式调试中, (系统) 线程的数据偏移量是该线程的 TEB 位置。 在内核模式调试中, (虚拟) 线程的数据偏移量是发生最后一个事件时在相应处理器上运行的系统线程的 KTHREAD 结构。 可以使用 GetCurrentThreadDataOffset 找到当前线程的数据偏移量。 对于给定的数据偏移量,可以使用 GetThreadIdByDataOffset 找到相应的引擎线程 ID。

系统句柄
可以使用 GetCurrentThreadHandle 找到当前线程的系统句柄。 对于给定的系统句柄,可以使用 GetThreadIdByHandle 找到相应的引擎线程 ID。 在内核模式调试中,为每个 (虚拟) 进程创建一个人工句柄。 此句柄只能与调试器引擎 API 查询一起使用。

过程

调试器 引擎使用引擎进程 ID 来标识目标的每个操作系统进程和每个虚拟进程。

停止目标时,每个进程都有一个相对于目标的索引。 目标中第一个进程的索引为零,最后一个进程的索引是目标中的进程数减 1。 可以使用 GetNumberProcesses 找到当前目标中的进程数。

可以使用 GetProcessIdsByIndex 从当前目标中的一个或多个线程的索引中找到引擎进程 ID 和系统进程 ID。

引擎维护有关每个进程的几条信息。 此信息可以查询当前进程,并可用于查找进程的引擎进程 ID。

仅) (用户模式调试的系统进程 ID
可以使用 GetCurrentProcessSystemId 找到当前进程的系统进程 ID。 对于给定的系统进程 ID,可以使用 GetProcessIdBySystemId 找到相应的引擎进程 ID。

处理环境块 (PEB)
可以使用 GetCurrentProcessPeb 找到当前进程的 PEB 地址。 对于给定的 PEB 地址,可以使用 GetProcessIdByPeb 找到相应的引擎进程 ID。 在内核模式调试中, (虚拟) 进程的 PEB 是上次事件发生时正在运行的系统进程的 PEB。

数据偏移量
在用户模式调试中, (系统) 进程的数据偏移量是该进程的 PEB 位置。 在内核模式调试中, (虚拟) 进程的数据偏移量是上次事件发生时正在运行的系统进程的 KPROCESS 结构。 可以使用 GetCurrentProcessDataOffset 找到当前进程的数据偏移量。 对于给定的数据偏移量,可以使用 GetProcessIdByDataOffset 找到相应的引擎进程 ID。

系统句柄
可以使用 GetCurrentProcessHandle 找到当前进程的系统句柄。 对于给定的系统句柄,可以使用 GetProcessIdByHandle 找到相应的引擎进程 ID。 在内核模式调试中,为 (虚拟) 进程创建人工句柄。 此句柄只能与调试器引擎查询一起使用。

事件

在实时用户模式调试中,每当在目标中创建或退出线程时,都会生成 create-thread 和 exit-thread 调试事件。 这些事件会导致调用 IDebugEventCallbacks::CreateThreadIDebugEventCallbacks::ExitThread 回调方法。

在实时用户模式调试中,每当在目标中创建或退出进程时,都会生成 create-process 和 exit-process 调试事件。 这些事件会导致调用 IDebugEventCallbacks::CreateProcessIDebugEventCallbacks::ExitProcess 回调方法。

有关事件的详细信息,请参阅 监视事件

其他信息

有关线程和进程(包括 TEB、KTHREAD、PEB 和 KPROCESS 结构)的详细信息,请参阅 Microsoft Windows Internals by David Solomon 和 Mark Russinovich。