调试器如何跟踪堆栈?

Posted

技术标签:

【中文标题】调试器如何跟踪堆栈?【英文标题】:How debuggers can trace the stack? 【发布时间】:2021-09-28 03:11:03 【问题描述】:

我试图使用堆栈指针来实现堆栈跟踪器; RSP 和 RBP,但我认为调试器使用完全不同的方式来获取返回地址,或者我可能遗漏了一些东西。我可以抓取最后一个栈帧的返回地址,但是我无法获取其他的,因为我不知道其他栈帧的大小,所以我无法弄清楚我应该从栈帧返回多少字节, 获取返回地址。有谁知道调试器使用哪种方式来跟踪堆栈?

【问题讨论】:

【参考方案1】:

当代码使用帧指针时,可以跟踪堆栈。在这种情况下,ebp/rbp 用作帧指针,函数以序言开头,以结尾结尾。 一个典型的 prolog 如下所示:

push    rbp       ; save previous frame pointer
mov     rbp, rsp  ; initialize this functions frame pointer

典型的结语如下所示:

mov     rsp, rbp  ; restore the value of rsp
pop     rbp       ; restore previous frame pointer value from stack
retn

因此,函数rbp 的每个位置都指向保存前一帧指针的堆栈位置,rbp+8 包含保存的返回地址。 要获取被调用函数,调试器应读取[rbp+8] 值并找到该地址所属的函数。这可以通过在调试符号中搜索来完成。 接下来它应该读取[rbp] 值以获取调用函数的帧指针。继续此过程,直到找到顶层函数。这通常是一个启动线程的系统库函数。

【讨论】:

太酷了。我从来没有那样想。谢谢

以上是关于调试器如何跟踪堆栈?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 perf 收集一些可读的堆栈跟踪?

Javascript 异常堆栈跟踪

NullReferenceException,没有堆栈跟踪......从哪里开始?

GDB堆栈跟踪与汇编调试

如何设置 Visual Studio 以显示第一次机会异常的堆栈跟踪?

调试 logcat 堆栈跟踪 - 没有例程信息