2

例如,我想在 Windows 下实现一个类似的回溯实用程序,以便将此信息添加到异常中。

我需要捕获返回地址,然后将其转换为符号名称。

我知道 StackWalk64 和StackWalker 项目,但不幸的是它有几个重要的缺点:

  • 众所周知它非常慢(StackWalk64),我不想浪费太多时间来收集跟踪,基本上可以像在链表上行走一样快。
  • 已知函数 StackWalk64 不是线程安全的。

我只想支持 x86 和可能的 x86_64 架构

我的基本想法如下:

  1. 使用 esp/ebp 寄存器在堆栈上运行,类似于 GCC 的__builtin_return_address(x)/ __builtin_frame_address(x)doe 直到我到达堆栈底部(这就是 glibc 所做的)。
  2. 将地址转换为符号
  3. 拆解它们。

问题/疑问:

  1. 我怎么知道我到达了堆栈的终点?例如 glibc 实现有__libc_stack_end,所以很容易找到停止的地方。Windows下有类似的东西吗?如何获取栈底地址?
  2. dladdr 功能的类似物是什么。现在我知道,与保留大部分符号名称的 ELF 平台不同,PE 格式没有。所以它应该以某种方式读取调试信息。有任何想法吗?
4

2 回答 2

2
  • 捕获堆栈跟踪:RtlCaptureStackBackTrace
  • 获取符号:使用 DBG 帮助库(仅限 MSVC)。主要功能:

    // Initialization
    hProcess = GetCurrentProcess()
    SymSetOptions(SYMOPT_DEFERRED_LOADS)
    SymInitialize(hProcess, NULL, TRUE)
    // Fetching symbol
    SymFromAddr(...)
    

    可以在那里找到实现

于 2011-02-14T10:30:06.380 回答
1

StackWalk稍后使用但解析符号。

于 2010-09-27T10:19:01.623 回答