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

发布于 2024-09-27 07:53:18 字数 175 浏览 7 评论 0原文

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

I enumerate all threads in a process through the CreateToolhelp32Snapshot function. 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 ~*k command in WinDbg. So how can I obtain the stack information from the thread's ID or HANDLE?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

却一份温柔 2024-10-04 07:53:18

(可以在此处找到定义。)

获取堆栈边界:

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

获取esp,只需使用 GetThreadContext

(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.

不语却知心 2024-10-04 07:53:18

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

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

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

NT_TIB* tib = (NT_TIB*)__readfsdword(0x18);
size_t* stackBottom = (size_t*)tib->StackLimit;
size_t* stackTop = (size_t*)tib->StackBase;
吃素的狼 2024-10-04 07:53:18

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

添加了 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;

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

Added some declarations which are missed in 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;
霓裳挽歌倾城醉 2024-10-04 07:53:18

这是当前线程(可移植的 Win32 x86/x64 版本)的简单方法:

#include <intrin.h>

NT_TIB* getTIB() {
#ifdef _M_IX86
  return (NT_TIB*)__readfsdword(0x18);
#elif _M_AMD64
  return (NT_TIB*)__readgsqword(0x30);
#else
#error unsupported architecture
#endif
}

  NT_TIB* tib = getTIB();
  void* stackBase = tib->StackBase;
  void* stackLimit = tib->StackLimit;

注意:stackLimit stackLimit stackLimit stackBase(堆栈向下增长)。

有关更多详细信息,请参阅 Win32 TIB

Here's an easy way for the current thread (portable Win32 x86/x64 version):

#include <intrin.h>

NT_TIB* getTIB() {
#ifdef _M_IX86
  return (NT_TIB*)__readfsdword(0x18);
#elif _M_AMD64
  return (NT_TIB*)__readgsqword(0x30);
#else
#error unsupported architecture
#endif
}

  NT_TIB* tib = getTIB();
  void* stackBase = tib->StackBase;
  void* stackLimit = tib->StackLimit;

Note: stackLimit < stackBase (as stack grows downwards).

For more details refer to Win32 TIB.

少女七分熟 2024-10-04 07:53:18

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文