glibc backtrace() 如何确定哪个堆栈内存是 return 地址?

How does glibc backtrace() determine which stack memory are the return addresses?

对于程序来说,栈就是一堆内存。回溯函数如何确定哪些堆栈字节是指令指针 return 地址,哪些只是函数参数等?

As far as a program is concerned, a stack is just a bunch of memory.

没错。如果您对程序的结构一无所知,您将无法展开它的堆栈。

用于展开的最简单结构是保留单个“帧指针”寄存器以始终指向当前帧的结构,并且该帧包含 前一个 帧指针一个已知的偏移量。

这是在 i*86 上使用了很长时间的机制,并且仍在许多 RISC 机器上使用。它使堆栈展开变得容易且非常快,但它在寄存器匮乏的机器上效率不高,例如 i*x86 和较低程度的 x86_64,因为该帧寄存器可以在其他地方更好地使用。

解决方案是创建增强数据,它描述了如何在给定当前寄存器组和内存内容的情况下找到当前帧(例如“当前帧位于 [=NN 的偏移量 $rsp”,或“在 $rbp 的偏移量 MM 处”,“前一帧在当前帧的偏移量 J 处”,等等)

这实际上就是 .eh_frame 的意思。从您的二进制文件中将其删除,将无法展开堆栈。

这种机制也比简单的帧指针遍历慢得多,需要复杂的代码,而且容易出错(编译器不能保证发出正确的展开描述符,手工编码的汇编可能根本没有它们) .

other solutions 可以使展开变得快速和容易,但它们需要不同的调用约定。