如何在 Windows 上获取线程堆栈信息?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3918375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:23:57  来源:igfitidea点击:

How to get thread stack information on Windows?

windowsstackwindbg

提问by user473750

I enumerate all threads in a process through the CreateToolhelp32Snapshotfunction. I would like to get some basic stack information for each thread. More specifically I would like to get stack bottom address and if possible I would like to get current stack top address. Basically this is the information displayed with the ~*kcommand in WinDbg. So how can I obtain the stack information from the thread's ID or HANDLE?

我通过CreateToolhelp32Snapshot函数枚举了一个进程中的所有线程。我想为每个线程获取一些基本的堆栈信息。更具体地说,我想获得堆栈底部地址,如果可能的话,我想获得当前堆栈顶部地址。基本上这是~*k在 WinDbg 中使用命令显示的信息。那么如何从线程的 ID 或 HANDLE 中获取堆栈信息呢?

回答by wj32

(Definitions can be found here.)

(定义可以在这里找到。)

To get stack boundaries:

获取堆栈边界:

THREAD_BASIC_INFORMATION basicInfo;
NT_TIB tib;

// Get TEB address
NtQueryInformationThread(YOUR_THREAD_HANDLE, ThreadBasicInformation, &basicInfo, sizeof(THREAD_BASIC_INFORMATION), NULL);
// Read TIB
NtReadVirtualMemory(YOUR_PROCESS_HANDLE, basicInfo.TebBaseAddress, &tib, sizeof(NT_TIB), NULL);
// Check tib.StackBase and tib.StackLimit

To get the value of esp, simply use GetThreadContext.

要获得 的值esp,只需使用GetThreadContext.

回答by Thomas Johnstone

An easier way without having to involve the Windows Driver Kit is as so:

无需涉及 Windows 驱动程序工具包的更简单方法如下:

NT_TIB* tib = (NT_TIB*)__readfsdword(0x18);
size_t* stackBottom = (size_t*)tib->StackLimit;
size_t* stackTop = (size_t*)tib->StackBase;

回答by Mikhail Pilin

__readfsdword() works only for the current thread. So, the variant with NtQueryInformationThread() is more flexible.

__readfsdword() 仅适用于当前线程。因此,带有 NtQueryInformationThread() 的变体更加灵活。

Added some declarations which are missed in ntdll.h:

添加了一些在 ntdll.h 中遗漏的声明:

typedef enum _THREADINFOCLASS {
    ThreadBasicInformation = 0,
} THREADINFOCLASS;

typedef LONG KPRIORITY;

typedef struct _CLIENT_ID {
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID *PCLIENT_ID;

typedef struct _THREAD_BASIC_INFORMATION
{
  NTSTATUS                ExitStatus;
  PVOID                   TebBaseAddress;
  CLIENT_ID               ClientId;
  KAFFINITY               AffinityMask;
  KPRIORITY               Priority;
  KPRIORITY               BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;

回答by plodoc

As fas as I know, Toolhelp works by making a copy of basic information on heaps, modules, processes and threads. This does not include the TEB block that contains the stack bottom address. I think you need to use another API, the debugger engine API, which offers functions to examine the stacks

据我所知,Toolhelp 的工作原理是复制有关堆、模块、进程和线程的基本信息。这不包括包含堆栈底部地址的 TEB 块。我认为您需要使用另一个 API,即调试器引擎 API,它提供检查堆栈的功能