内存栈的遍历是如何完成的?

问题描述

假设这个简单的 C 代码

int test(int in){
 return in;
}

int main(){
 return test(5);
}

看起来就像是 AS:

_test:
    pushq   %rbp
    movq    %rsp,%rbp
    movl    %edi,-4(%rbp)
    movl    -4(%rbp),%eax
    popq    %rbp
    retq
_main:
    pushq   %rbp
    movq    %rsp,%rbp
    subq    $16,%rsp
    movl    $0,-4(%rbp)
    movl    $5,%edi
    callq   _test
    addq    $16,%rsp
    popq    %rbp
    retq

假设我在 _test: 中执行代码并且它在中途崩溃并且我喜欢生成一个 stack trace。怎么做的?

我知道该方法名为 stack walking。 我也知道这取决于架构,并且有多种方法可以做到。在 x86 上,我们可以依靠 base pointer register $rbp。堆栈上的 $rbp 值等于一个新框架(以及一个正在执行的新函数)。

现在我们是真的遍历堆栈还是依赖生成的指令?

如果我们只遍历内存堆栈,我们怎么知道我们现在正在查看的值是什么?我们如何知道在我们命中先前存储的 base pointer 之前要回读多少?堆栈可以包含不同大小的整数、短字符、字符的组合。即使我们命中了一个指针值,我们如何确认它是指针?

我猜我们还需要查看生成的指令,从 program counter 指向的位置开始并向上移动。使用这个我们可以知道堆栈上的值是什么样的?我说得对吗?

这里有更多细节: https://www.sciencedirect.com/science/article/pii/S1742287618300458

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)